SQL:需要删除包含多个连接的查询中的重复行

时间:2010-08-26 17:58:55

标签: sql

请注意,我是一个完整的SQL菜鸟,正在学习中。基于谷歌搜索(包括在这里搜索),我尝试使用SELECT DISTINCT和GROUP BY,但两者都没有用,可能是由于我的所有联接(如果有人知道它们为什么不能正常工作,那将有助于学习)。

我需要来自各种表格和下面的数据是我知道的唯一方法(我只知道基础知识)。下面的查询工作正常,但显示重复。我需要知道如何删除它们。我现在唯一的提示可能是嵌套的SELECT查询,但基于研究,我不知道如何实现它们。任何帮助都会很棒,谢谢!

USE SQL_Contest
go
SELECT
    CLT.Description AS ClockType,
    CLK.SerialNumber AS JobClockSerial,
    SIT.SiteNumber AS JobID,
    SIT.[Name] AS JobsiteName,
    SIT.Status AS SiteActivityStatus,
    DHA.IssuedDate AS DHAIssuedDate, -- Date the clock was assigned to THAT jobsite
    CLK.CreatedDate AS CLKCreatedDate, -- Date clock first was assigned to ANY jobsite
    SES.ClockVoltage
FROM tb_Clock CLK
INNER JOIN tb_ClockType CLT
ON CLK.TypeID = CLT.ClockTypeID
INNER JOIN tb_DeviceHolderActivity DHA
ON CLK.ClockGUID = DHA.DeviceGUID
INNER JOIN tb_Site SIT
ON SIT.SiteGUID = DHA.HolderGUID
LEFT JOIN tb_Session SES
ON SES.ClockSerialNumber = CLK.SerialNumber
WHERE DHA.ReturnedDate IS NULL
ORDER BY SIT.[Name] ASC
编辑:我将很快回顾这些答案,非常感谢你。我根据Rob的要求发布了额外的重复信息:

在我添加之前,一切都很好:

LEFT JOIN tb_Session SES
ON SES.ClockSerialNumber = CLK.SerialNumber

我需要的。那是出现重复的时候:

JobClock 2,500248E4,08-107,Brentwood Job,1,2007-05-04 13:36:54.000,2007-05-04 13:47:55.407,3049    
JobClock 2,500248E4,08-107,Brentwood Job,1,2007-05-04 13:36:54.000,2007-05-04 13:47:55.407,3049

我希望这些信息只显示一次。本质上,这个查询是确定所有分配了时钟的活动作业现场,并且该作业只分配了一个时钟,并且它只有一个作业现场,但它出现了两次。

编辑2:根据你们提供的帮助,我能够确定它们实际上并不重复,并且每个会话都是独立的,这是唯一一个碰巧有两个会话的会话。所以现在我将尝试弄清楚如何仅从最新的会话中提取信息。

3 个答案:

答案 0 :(得分:3)

如果一切都“正常”,直到你添加:

LEFT JOIN tb_Session SES
ON SES.ClockSerialNumber = CLK.SerialNumber

然后每个CLK.SerialNumber在tb_Session中必须有多个记录。

运行以下查询:

SELECT  *
FROM    tb_Session SES
WHERE   ClockSerialNumber = '08-107'

应该返回两条记录。您需要决定如何处理这个问题(即您要使用哪条记录?),除非tb_Session中的两行都包含相同的数据,在这种情况下,它们是否应该?

您可以随时将查询更改为:

SELECT
    CLT.Description AS ClockType,
    CLK.SerialNumber AS JobClockSerial,
    SIT.SiteNumber AS JobID,
    SIT.[Name] AS JobsiteName,
    SIT.Status AS SiteActivityStatus,
    DHA.IssuedDate AS DHAIssuedDate, -- Date the clock was assigned to THAT jobsite
    CLK.CreatedDate AS CLKCreatedDate, -- Date clock first was assigned to ANY jobsite
    SES.ClockVoltage
FROM tb_Clock CLK
INNER JOIN tb_ClockType CLT
ON CLK.TypeID = CLT.ClockTypeID
INNER JOIN tb_DeviceHolderActivity DHA
ON CLK.ClockGUID = DHA.DeviceGUID
INNER JOIN tb_Site SIT
ON SIT.SiteGUID = DHA.HolderGUID
LEFT JOIN 
(
    SELECT DISTINCT ClockSerialNumber, ClockVoltage
    FROM tb_Session 
) SES
ON SES.ClockSerialNumber = CLK.SerialNumber
WHERE DHA.ReturnedDate IS NULL
ORDER BY SIT.[Name] ASC

因为这应确保SES仅包含ClockSerialNumberClockVoltage

的每个唯一组合的一条记录

答案 1 :(得分:1)

以此示例数据集:

<强>成分

IngredientId IngredientName
============ =========
1            Apple
2            Orange
3            Pear
4            Tomato

<强>配方

RecipeId RecipeName
======== ==========
1        Apple Turnover
2        Apple Pie
3        Poached Pears

<强> Recipe_Ingredient

RecipeId IngredientId Quantity
======== ============ ========
1        1            0.25
1        1            1.00
2        1            2.00
3        3            1.00
  

注意: 为什么Apple Turnover有两批苹果作为成分,既不在这里也不在那里,只是它。

以下查询将返回“Apple Turnover”配方的两行,“Apple Pie”配方的一行和“Poached Pears”配方的一行,因为有两个条目在IngredientId的Recipe_Ingredient表中1.这就是加入时发生的事情..

SELECT  I.IngredientName,
        R.RecipeName
FROM    Ingredient I
JOIN    Recipe_Ingredient RI
        ON I.IngredientId = RI.IngredientId
JOIN    Recipe R
        ON RI.recipeId = R.RecipeId

您可以通过将其更改为:

来仅返回一行
SELECT  I.IngredientName,
        R.RecipeName
FROM    Ingredient I
JOIN    Recipe_Ingredient RI
        ON I.IngredientId = RI.IngredientId
JOIN    Recipe R
        ON RI.recipeId = R.RecipeId
GROUP BY I.IngredientName, R.RecipeName

如果没有关于您的数据的更多细节,很难将其应用于您的特定场景,但演练可以帮助您了解“重复”来自不熟悉SQL的人的位置

答案 2 :(得分:0)

联接不是你的问题。根据您的评论,我将推断您所谓的“重复”并非实际重复。如果从匹配的查询返回的2“重复”的所有列值,则SELECT DISTINCT或GROUP BY肯定会消除它们。因此,您应该能够通过查看列定义来找到解决方案。

我最好的猜测是,由于日期的时间成分不匹配,您在相同日期获得的重复项并非真正重复。要消除此问题,您只能使用以下技术将日期字段截断为日期:

    DATEADD(DAY, DATEDIFF(DAY, 0, DHA.IssuedDate), 0) AS DHAIssuedDate,
    DATEADD(DAY, DATEDIFF(DAY, 0, CLK.CreatedDate), 0) AS CLKCreatedDate,   

如果这不起作用,您可能需要查看JobClockSerial:此列是否属于查询结果?