【问题标题】:Joining multiple tables returning duplicates连接多个返回重复项的表
【发布时间】:2015-03-22 17:10:37
【问题描述】:

我正在尝试以下选择语句,包括来自 4 个表的列。但是结果每行返回 4 次,我确定这是因为我有多个左连接,但我尝试了其他连接并且无法获得所需的结果。

    select table1.empid,table2.name,table2.datefrom, table2.UserDefNumber1, table3.UserDefNumber1, table4.UserDefChar6
from table1
inner join table2
on table2.empid=table1.empid
inner join table3
on table3.empid=table1.empid
inner join table4
on table4.empid=table1.empid

where MONTH(table2.datefrom) = Month (Getdate())

我需要这个来返回没有任何重复的数据,所以每个条目只有 1 行。

我还希望末尾的“where Month”子句查看上个月,而不是当前月份,但也要为此苦苦挣扎。

我对此有点陌生,所以我希望它有意义。

谢谢

【问题讨论】:

标签: sql sql-server select join inner-join


【解决方案1】:

如果每列的重复行相同,您可以使用 DISTINCT 关键字来消除这些重复。

但我认为您应该重新考虑您的 JOINWHERE 子句,因为这些重复必须有原因:

  1. WHERE 子句在单个 empid 上命中 table2 中具有相同月份的几行
  2. 在其他一个表中有几行具有相同的 empid
  3. 以上都属实

您可能希望通过 WHERE/JOIN 中的条件而不是 DISTINCT 关键字来排除那些重复的行,因为当原始结果集中的单行中的某些数据发生更改时,可能会出现意外行为。然后你又开始有重复的empid了。

您可以通过以下子句检查日期是否在上个月:

date BETWEEN dateadd(mm, -1, datefromparts(year(getdate()), month(getdate()), 1)) 
AND datefromparts(year(getdate()), month(getdate()), 1)

此语句使用DATEFROMPARTS 两次创建当月的月初,使用DATEADD 从第一个中减去一个月(结果为上月初)并检查date 是否介于两者之间日期使用BETWEEN

【讨论】:

    【解决方案2】:

    如果您的查询返回重复项,则一个或多个表具有重复的 empid 值。这是一个数据问题。您可以通过以下查询找到它们:

    select empid, count(*)
    from table1
    group by empid
    having count(*) > 1;
    

    您应该真正修复数据和查询,以便它返回您想要的。您可以使用select distinct 进行绷带解决方案,但我通常不建议这样做。某些原因导致重复,如果您不明白原因,则查询可能不会返回您期望的结果。

    至于您的where 子句。鉴于您的逻辑,表达这一点的正确方法包括年份:

    where year(table2.datefrom) = year(getdate()) and
          month(table2.datefrom) = month(Getdate())
    

    虽然还有其他方法可以表达这种逻辑,与索引更兼容,但您可以继续本课程:

    where year(table2.datefrom) * 12 + month(table2.datefrom) = year(getdate()) * 12 + Month(Getdate()) - 1
    

    也就是说,将月份转换为从零开始的月份数,然后使用月份算术。

    如果您关心索引,那么您当前的 where 子句将如下所示:

    where table2.datefrom >= dateadd(day,
                                     - (day(getdate) - 1),
                                     cast(getdate() as date) and
          table2.datefrom < dateadd(day,
                                     - (dateadd(month, 1, getdate()) - 1),
                                     cast(dateadd(month, 1, getdate()) as date)
    

    【讨论】:

      【解决方案3】:

      通过在 select 之后立即包含 distinct 关键字来消除查询中的重复项

      与上个月相比稍微复杂一些。这取决于你的意思:

      如果报告是在 2015 年 1 月 23 日生成的,您想要 01/12/2014-31/12/2014 还是 23/12/2014-22/01/2015?

      【讨论】:

      • 感谢您的回复,因为它只需要是上一个日历月的日期,所以如果它在 2 月运行,它将返回从 1 月开始的所有内容,无论具体日期如何。
      猜你喜欢
      • 1970-01-01
      • 2012-12-20
      • 2021-12-05
      • 2021-03-07
      • 2019-01-13
      • 2021-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多