【问题标题】:How to do an outer join with count based column?如何使用基于计数的列进行外部连接?
【发布时间】:2010-09-22 16:31:08
【问题描述】:

SQL 2008 中以下问题的有效方法是什么?

前两个是输入表,我需要使用它来填充第三个(DataOut 表)

基本上,WDATA 将有零或多行对应于 DataIn 表的每一行。 我需要用所有行填充 DataOut 表,包括不匹配和多个匹配,并填充一个状态列,区分 WDATA 中的单个对应行、WDATA 中的无行或 WDATA 中的恰好一行。

DataIn
QID  RID  DOB
-------------
1    1    01/01/1980
1    2    03/01/1981
1    3    01/02/1991



WDATA(key is QID, RID,PID)
QID  RID  PID
---------------
1    1    101
1    1    102
1    3    204



DataOut
QID  RID  PID  status
-----------------------
1    1    101  ”multiple match”
1    1    102  ”multiple match”
1    2    null ”no match”
1    3    204  ”single match”

【问题讨论】:

    标签: sql sql-server-2008 join


    【解决方案1】:

    这里的查询怎么样??

    SELECT
        di.QID, di.RID, w.PID,
        CASE (SELECT COUNT(*) FROM WDATA w2 WHERE di.QID = w2.QID AND di.RID = w2.RID)
            WHEN 0 THEN 'no match'
            WHEN 1 THEN 'single match'
            ELSE 'multiple match'
        END AS 'Status'
    FROM
        DataIn di 
    LEFT OUTER JOIN 
        WDATA w ON di.QID = w.QID AND di.RID = w.RID
    

    对我来说,它会产生以下输出:

    QID  RID  PID   Status
     1    1   101   multiple match
     1    1   102   multiple match
     1    2   NULL  no match
     1    3   204   single match
    

    这就是你要找的吗??

    【讨论】:

    • 谢谢!让我在我的数据上试试这个
    【解决方案2】:

    这看起来不错,不过我认为它可以改进。

    DECLARE @DataIn TABLE
    (
        QID INT NOT NULL,
        RID INT NOT NULL,
        DOB DATE NOT NULL
    )
    INSERT INTO @DataIn
    VALUES
    (1,1,'01/01/1980'),
    (1,2,'03/01/1981'),
    (1,3,'01/02/1991')
    
    DECLARE @WDATA TABLE
    (
        QID INT NOT NULL,
        RID INT NOT NULL,
        PID INT NOT NULL        
    )
    INSERT INTO @WDATA
    VALUES
    (1,1,101),
    (1,1,102),
    (1,3,204)
    
    ;WITH OuterCTE(QID, RID, PID) AS
    (
    SELECT 
        ISNULL(D.QID, W.QID) AS QID,
        ISNULL(D.RID, W.RID) AS RID,    
        W.PID
    FROM @DataIn AS D FULL OUTER JOIN @WDATA AS W ON W.RID = D.RID AND W.QID = D.QID
    )
    
    SELECT
        CTE.QID,
        CTE.RID,
        CTE.PID,
        CASE 
            WHEN COUNT(W.PID) = 0 THEN 'no match'
            WHEN COUNT(W.PID) = 1 THEN 'single match'
            ELSE 'multiple match'
        END
    FROM
        OuterCTE AS CTE
        LEFT JOIN @WDATA AS W 
        ON CTE.QID = W.QID 
        AND CTE.RID = W.RID
    GROUP BY
        CTE.QID,
        CTE.RID,
        CTE.PID
    

    【讨论】:

      【解决方案3】:

      试试这个:

      SELECT di.QID,di.RID,wd.PID, 
      CASE 
         WHEN  wd.PID is null THEN 'no match'
         WHEN COUNT(di.QID) = 1 THEN 'single match'
         WHEN COUNT(di.QID) > 1 THEN 'multiple match'
      END
      FROM DataIn as di
      LEFT JOIN WDATA as wd
      ON di.QID = wd.QID AND di.RID = wd.RID
      GROUP BY di.QID,di.RID,wd.PID
      

      【讨论】:

      • 你错过了“GROUP BY di.QID,di.RID,wd.PID”但是你的比我的好:/
      • 看起来干净紧凑,还省了一笔!现在检查我的数据。
      • 在您的 GROUP BY di.QID,di.RID,wd.PID 行中,由于 PID 分组,查询不会创建多个匹配的任何记录,因为两行上的 PID 会不同。知道我可以在这里解决什么问题吗?
      • 基本上,目前对于如上图类似的数据,即使是多行的行,都给出count=1
      猜你喜欢
      • 1970-01-01
      • 2019-07-29
      • 1970-01-01
      • 2012-12-31
      • 1970-01-01
      • 1970-01-01
      • 2011-10-28
      • 2016-05-10
      • 1970-01-01
      相关资源
      最近更新 更多