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 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 Offline
        Richard DeemingR Offline
        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 Offline
                Richard DeemingR Offline
                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