SQL group-by on column(Value)仅适用于其他列中具有重复项的行(Count(ID)> 1)

时间:2013-01-19 11:40:37

标签: sql group-by

我有一个与此类似的表,输入SQL

    ID                     Value
    FRY6040501ACH19        1388
    FRY6040501ACH19        1389
    FRY6040501ACH19        1388
    <Null>                 13800
    <Null>                 13800
    <Null>                 <Null>
    0026003710022745       1388
    0026003710022752       <Null>
    0026003710022751       32750
    0026003710022751       32750
    0026003710022751       32750

我需要编写一个SQL来获取带有额外Status列的输出。

我正在添加中间列TmpCntID&amp; TmpCntVl解释逻辑

所需的SQL输出如下:( TmpCntID&amp; TmpCntVl不需要)

    ID               TmpCntID     Value    TmpCntVl   Status
    FRY6040501ACH19      3        1388       2        MisMatch
    FRY6040501ACH19      3        1389       1        MisMatch
    FRY6040501ACH19      3        1388       2        MisMatch
    <Null>               3        13800      2        MisMatch
    <Null>               3        13800      2        MisMatch
    <Null>               3        <Null>     1        MisMatch
    0026003710022745     1        1388       1        NA
    0026003710022752     1        <Null>     1        NA
    0026003710022751     3        32750      3        Match
    0026003710022751     3        32750      3        Match
    0026003710022751     3        32750      3        Match

此处使用的逻辑首先使用SELECT ID, Count(*) FROM MyTable M GROUP BY IIF(IsNull(ID), '0', ID), ID having COUNT(*)>1重复ID,以获取中间输出

    NDUPID            TmpCntID
    FRY6040501ACH19      3
    <Null>               3
    0026003710022751     3

现在,我们需要忽略ID的其余部分,例如00260037100227450026003710022752

ID中的每个NDUPID (above intermediate output)的上方第一个表中查找非重复values。任何一个非重复的必须指出具有相同ID的所有行为Mismatch

对于针对ID=0026003710022751的示例,我们可以看到所有三个values=32750,因此Status=Match以及ID=FRY6040501ACH19ID=<Null>我们至少有一个重复{ {1}}因此它是value

在上面的输出表中,对于Status=Mismatch的所有行,我们需要TmpCntID=1

逻辑是首先计算Status=NATmpCntVl然后在最终输出中不需要,然后使用case语句,如果两列相等,则 TmpCntID 如果两列不相等,则 Match 以及上面中间输出表中的所有MisMatch,即{{ 1}}状态为 ID

非常感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

我可能遗漏了一些内容,但看起来您希望Status列定义为:

SELECT CASE WHEN TmpCntID = 1 THEN 'NA'
     WHEN EXISTS(SELECT 1 FROM interTbl tt 
                 WHERE tt.ID = tbl.ID AND tt.TmpCntVl = 1)
          THEN 'MisMatch'
     ELSE 'Match'
END AS Status
FROM interTbl tbl

即,

  • NA独特时
  • MisMatch的任何TmpCntVl为1 时,
  • ID
  • Match否则

我误解了这个问题,因为你知道如何获得中间输出,并且不知道如何从那里开始。这就是我要做的事情:

WITH Counts AS
(
    SELECT ID, Count(*) AS TmpCntID
    FROM myTable
    GROUP BY ID
),
LoneValues AS
(
    SELECT ID
    FROM myTable
    GROUP BY ID, Value
    HAVING COUNT(*) = 1
)
SELECT myTable.ID, myTable.Value,
    CASE WHEN Counts.TmpCntID = 1 THEN 'NA'
         WHEN EXISTS(SELECT 1 FROM LoneValues WHERE myTable.ID = LoneValues.ID
                           OR (myTable.ID IS NULL AND LoneValues.ID IS NULL))
              THEN 'MisMatch'
         ELSE 'Match'
    END AS Status
FROM myTable
INNER JOIN Counts ON myTable.ID = Counts.ID 
    OR (myTable.ID IS NULL AND Counts.ID IS NULL)

我不保证这是最佳解决方案,因此如果以后出现问题,您可以考虑如何修复它。

我还tried this query on SQL Fiddle,所以你可以看到它的实际效果。如果您的RDBMS不支持CTE,您当然可以在必要时将它们作为子查询粘贴。