Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Database & SysAdmin
  3. Database
  4. Prioritized joining - Updated

Prioritized joining - Updated

Scheduled Pinned Locked Moved Database
11 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    Jorgen Andersson
    wrote on last edited by
    #1

    I'm looking for a way of joining two tables using a function returning a ranking value where the rows joined would be decided on the returning value of a function. Assume I'm joining table X and Table Y using a function f(X,Y) If the values returned by the function from a cartesian join would be:

    X1

    X2

    X3

    Y1

    1

    5

    9

    Y2

    7

    3

    8

    Y3

    4

    2

    6

    I would want this "excluding functional join" to return: Y1,X3 Y2,X1 Y3,X2 Is this at all possible without using procedural code? <edit>What I want is something similar to the Gale-Shapley[^] algorithm but using a special text search instead of simple preferences. It's easy enough to do in procedural code, but I want to avoid an RBAR solution</edit>

    Wrong is evil and must be defeated. - Jeff Ello

    M Richard DeemingR 2 Replies Last reply
    0
    • J Jorgen Andersson

      I'm looking for a way of joining two tables using a function returning a ranking value where the rows joined would be decided on the returning value of a function. Assume I'm joining table X and Table Y using a function f(X,Y) If the values returned by the function from a cartesian join would be:

      X1

      X2

      X3

      Y1

      1

      5

      9

      Y2

      7

      3

      8

      Y3

      4

      2

      6

      I would want this "excluding functional join" to return: Y1,X3 Y2,X1 Y3,X2 Is this at all possible without using procedural code? <edit>What I want is something similar to the Gale-Shapley[^] algorithm but using a special text search instead of simple preferences. It's easy enough to do in procedural code, but I want to avoid an RBAR solution</edit>

      Wrong is evil and must be defeated. - Jeff Ello

      M Offline
      M Offline
      Mycroft Holmes
      wrote on last edited by
      #2

      Jörgen Andersson wrote:

      without using procedural code

      I do doubt it. One way might be to create a separate view that generates the ranking (can't see the PK field) and use the view in the join.

      Never underestimate the power of human stupidity RAH

      J 1 Reply Last reply
      0
      • M Mycroft Holmes

        Jörgen Andersson wrote:

        without using procedural code

        I do doubt it. One way might be to create a separate view that generates the ranking (can't see the PK field) and use the view in the join.

        Never underestimate the power of human stupidity RAH

        J Offline
        J Offline
        Jorgen Andersson
        wrote on last edited by
        #3

        Mycroft Holmes wrote:

        can't see the PK field

        That's because they're of no use in this case. I'm trying to map two tables in two different databases on their description fields, and some descriptions are basically the same but with added information for some rows, and those are the big problem. I'm going to try to do it using a recursive CTE.

        Wrong is evil and must be defeated. - Jeff Ello

        M 1 Reply Last reply
        0
        • J Jorgen Andersson

          I'm looking for a way of joining two tables using a function returning a ranking value where the rows joined would be decided on the returning value of a function. Assume I'm joining table X and Table Y using a function f(X,Y) If the values returned by the function from a cartesian join would be:

          X1

          X2

          X3

          Y1

          1

          5

          9

          Y2

          7

          3

          8

          Y3

          4

          2

          6

          I would want this "excluding functional join" to return: Y1,X3 Y2,X1 Y3,X2 Is this at all possible without using procedural code? <edit>What I want is something similar to the Gale-Shapley[^] algorithm but using a special text search instead of simple preferences. It's easy enough to do in procedural code, but I want to avoid an RBAR solution</edit>

          Wrong is evil and must be defeated. - Jeff Ello

          Richard DeemingR Online
          Richard DeemingR Online
          Richard Deeming
          wrote on last edited by
          #4

          How about something like this:

          1. Cross-join the two tables;
          2. Generate the ranking value for each pair;
          3. Generate a ROW_NUMBER, partitioned by the primary key of Y, and ordered by the ranking value (descending);
          4. Select the rows where the row number is 1;

          WITH cteRanked As
          (
          SELECT
          X.PK As XPK,
          X.OtherColumnsFromX,
          Y.PK As YPK,
          Y.OtherColumnsFromY,
          RankingFunction(X.Value, Y.Value) As R
          FROM
          X CROSS JOIN Y
          ),
          cteOrdered As
          (
          SELECT
          XPK,
          OtherColumnsFromX,
          YPK,
          OtherColumnsFromY,
          ROW_NUMBER() OVER (PARTITION BY YPK ORDER BY R DESC) As RN
          FROM
          cteRanked
          )
          SELECT
          XPK,
          OtherColumnsFromX,
          YPK,
          OtherColumnsFromY
          FROM
          cteOrdered
          WHERE
          RN = 1
          ;


          "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

          "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

          J 2 Replies Last reply
          0
          • J Jorgen Andersson

            Mycroft Holmes wrote:

            can't see the PK field

            That's because they're of no use in this case. I'm trying to map two tables in two different databases on their description fields, and some descriptions are basically the same but with added information for some rows, and those are the big problem. I'm going to try to do it using a recursive CTE.

            Wrong is evil and must be defeated. - Jeff Ello

            M Offline
            M Offline
            Mycroft Holmes
            wrote on last edited by
            #5

            Jörgen Andersson wrote:

            m going to try to do it using a recursive CTE.

            why am I not surprised by that. Your cte skills seem to be quite adequate. Let us know if you achieve a solution

            Never underestimate the power of human stupidity RAH

            J 2 Replies Last reply
            0
            • Richard DeemingR Richard Deeming

              How about something like this:

              1. Cross-join the two tables;
              2. Generate the ranking value for each pair;
              3. Generate a ROW_NUMBER, partitioned by the primary key of Y, and ordered by the ranking value (descending);
              4. Select the rows where the row number is 1;

              WITH cteRanked As
              (
              SELECT
              X.PK As XPK,
              X.OtherColumnsFromX,
              Y.PK As YPK,
              Y.OtherColumnsFromY,
              RankingFunction(X.Value, Y.Value) As R
              FROM
              X CROSS JOIN Y
              ),
              cteOrdered As
              (
              SELECT
              XPK,
              OtherColumnsFromX,
              YPK,
              OtherColumnsFromY,
              ROW_NUMBER() OVER (PARTITION BY YPK ORDER BY R DESC) As RN
              FROM
              cteRanked
              )
              SELECT
              XPK,
              OtherColumnsFromX,
              YPK,
              OtherColumnsFromY
              FROM
              cteOrdered
              WHERE
              RN = 1
              ;


              "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

              J Offline
              J Offline
              Jorgen Andersson
              wrote on last edited by
              #6

              Not bad, but it's not going all the way. I need to partition it by both X and Y.

              Wrong is evil and must be defeated. - Jeff Ello

              Richard DeemingR 1 Reply Last reply
              0
              • M Mycroft Holmes

                Jörgen Andersson wrote:

                m going to try to do it using a recursive CTE.

                why am I not surprised by that. Your cte skills seem to be quite adequate. Let us know if you achieve a solution

                Never underestimate the power of human stupidity RAH

                J Offline
                J Offline
                Jorgen Andersson
                wrote on last edited by
                #7

                I believe I have found one, the proper test will be on Monday. But as it is done using a recursive CTE, it's not the most effective one. I'm going to have another look at Richards version tonight.

                Wrong is evil and must be defeated. - Jeff Ello

                1 Reply Last reply
                0
                • J Jorgen Andersson

                  Not bad, but it's not going all the way. I need to partition it by both X and Y.

                  Wrong is evil and must be defeated. - Jeff Ello

                  Richard DeemingR Online
                  Richard DeemingR Online
                  Richard Deeming
                  wrote on last edited by
                  #8

                  I must be missing something - surely, if you partitioned by both X and Y, you'd end up with the Cartesian product of the two tables? :confused:


                  "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                  "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

                  J 1 Reply Last reply
                  0
                  • Richard DeemingR Richard Deeming

                    I must be missing something - surely, if you partitioned by both X and Y, you'd end up with the Cartesian product of the two tables? :confused:


                    "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                    J Offline
                    J Offline
                    Jorgen Andersson
                    wrote on last edited by
                    #9

                    Well, that, is exactly my problem! :)

                    Wrong is evil and must be defeated. - Jeff Ello

                    1 Reply Last reply
                    0
                    • M Mycroft Holmes

                      Jörgen Andersson wrote:

                      m going to try to do it using a recursive CTE.

                      why am I not surprised by that. Your cte skills seem to be quite adequate. Let us know if you achieve a solution

                      Never underestimate the power of human stupidity RAH

                      J Offline
                      J Offline
                      Jorgen Andersson
                      wrote on last edited by
                      #10

                      In the end I ended up using a variant of Richards suggestion.

                      Wrong is evil and must be defeated. - Jeff Ello

                      1 Reply Last reply
                      0
                      • Richard DeemingR Richard Deeming

                        How about something like this:

                        1. Cross-join the two tables;
                        2. Generate the ranking value for each pair;
                        3. Generate a ROW_NUMBER, partitioned by the primary key of Y, and ordered by the ranking value (descending);
                        4. Select the rows where the row number is 1;

                        WITH cteRanked As
                        (
                        SELECT
                        X.PK As XPK,
                        X.OtherColumnsFromX,
                        Y.PK As YPK,
                        Y.OtherColumnsFromY,
                        RankingFunction(X.Value, Y.Value) As R
                        FROM
                        X CROSS JOIN Y
                        ),
                        cteOrdered As
                        (
                        SELECT
                        XPK,
                        OtherColumnsFromX,
                        YPK,
                        OtherColumnsFromY,
                        ROW_NUMBER() OVER (PARTITION BY YPK ORDER BY R DESC) As RN
                        FROM
                        cteRanked
                        )
                        SELECT
                        XPK,
                        OtherColumnsFromX,
                        YPK,
                        OtherColumnsFromY
                        FROM
                        cteOrdered
                        WHERE
                        RN = 1
                        ;


                        "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                        J Offline
                        J Offline
                        Jorgen Andersson
                        wrote on last edited by
                        #11

                        The data turned out to be a lot less ordered or rather more asymmetrical than expected (just like I should've expected :rolleyes:) And the mapping between the databases also turned out to be important in only one direction. So I ended up using a variant of your solution, but using RANK instead of ROW_NUMBER. Now I'm working on refining the ranking function for whenever I get duplicate matches

                        Wrong is evil and must be defeated. - Jeff Ello

                        1 Reply Last reply
                        0
                        Reply
                        • Reply as topic
                        Log in to reply
                        • Oldest to Newest
                        • Newest to Oldest
                        • Most Votes


                        • Login

                        • Don't have an account? Register

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • World
                        • Users
                        • Groups