【问题标题】:Cannot select distinct values on joins无法在连接上选择不同的值
【发布时间】:2020-02-19 08:17:16
【问题描述】:

需要连接不同的表,但在连接期间每列选择不同的行

我有以下表格:

Devices
-------
id
Device
Snid
locationid
planid

Locations
---------
id
location

Plans
------
id
plan

Assignments
-----------
id
deviceid
startdate
enddate

我试过的是这样的:

SELECT DISTINCT a.id, a.device, a.Snid, b.location, c.plan, d.startdate, d.enddate 
FROM Devices a 
LEFT JOIN Locations b on a.locationid=b.id 
LEFT JOIN Plans c on a.planid=c.id 
LEFT JOIN Assignments d on a.id=deviceid

如果在选择中,我删除分配列(开始日期、结束日期),然后我会得到正常结果,但我需要获取分配表列。但是,一旦我添加了列,我就无法获得不同的设备。

我想要得到的结果是设备表,其中包含计划和位置(用于计划和位置名称)以及分配开始日期和结束日期列的组合。并且拥有具有最新分配的唯一设备,在我的情况下应该有一个空白的结束日期列。

另外,我需要一个 totalassignments 列。我尝试在选择部分添加:

SUM(case when a.id=d.deviceid then 1 else 0) as totalassignments

但如果我使用它,我需要添加一个分组依据。在 group by 中,我需要包含所有列,然后我又失去了我的独特之处。

示例如下:

设备表

id  device  locationid  planid
2   computer    1         0
3   mobile      2         1
10  printer     1         1
12  scanner     1         1
32  tablet      1         1
42  tv          2         2
68  video       3         2
98  camera      0         0

位置表

ID  location
1   Storage
2   Office
3   Contractor

计划表

ID  Plan
1   Short-term
2   Long-term

分配表

id  deviceid    startdate   enddate
1      10      10/17/2019   2/23/2019
2      32      10/20/2019   
3      12      10/18/2019   11/1/2019
4      68       
5      98      10/15/2019   10/5/2019
6      42      10/23/2019   
7      10      10/1/2019      NULL
8       2      8/18/2019    10/21/2019
9       3      10/23/2020    NULL
10     12      10/2/2019     NULL

想要的结果

device  deviceid    location    plan    totalassignments    startdate   enddate
computer    2       Storage     NULL          1             8/18/2019 10/21/2019
mobile      3       Office    Short-term      1             10/23/2020  NULL
printer     10      Storage   Short-term      2             10/1/2019   NULL
scanner     12      Storage   Short-term      2             10/2/2019   NULL
tablet      32      Storage   Short-term      1             10/20/2019  
tv          42      Office    Long-term       1             10/23/2019  
video       68      ContractorLong-term       1                NULL     NULL
camera      98      NULL        NULL          1             10/15/2019  

如您所见,结果必须具有设备(使用内部连接替换 locationid 和 planid 以及相关位置和计划名称),每个设备都有分配数量,并且在此旁边有开始和结束日期最新分配(enddate为NULL时配置)

【问题讨论】:

  • 看起来像top-n-per-group 问题。

标签: sql sql-server left-join distinct


【解决方案1】:

这是因为你的列数据中的时间因素不一样。

CAST(d.startdate AS DATE) 将取消时间元素,仅保留日期

试试这个

SELECT DISTINCT a.id, a.device, a.Snid, b.location, c.plan, 
       CAST(d.startdate AS DATE), CAST(d.enddate AS DATE)
FROM Devices a LEFT JOIN Locations b on a.locationid=b.id 
LEFT JOIN Plans c on a.planid=c.id LEFT JOIN Assignments d on a.id=deviceid

如果你想包含聚合函数,那么,

SELECT DISTINCT a.id, a.device, a.Snid, b.location, c.plan, 
       CAST(d.startdate AS DATE), CAST(d.enddate AS DATE),
       SUM(case when a.id=d.deviceid then 1 else 0) as totalassignments
FROM Devices a LEFT JOIN Locations b on a.locationid=b.id 
LEFT JOIN Plans c on a.planid=c.id LEFT JOIN Assignments d on a.id=deviceid
GROUP BY a.id, a.device, a.Snid, b.location, c.plan, 
       CAST(d.startdate AS DATE), CAST(d.enddate AS DATE)

【讨论】:

  • 这不是问题。我没有选择日期的问题。所以如果我按照你看到的那样做(这是我没有强制转换的解决方案),那么如果一个设备被多次分配,我会得到重复的设备。
  • 发布样本数据和预期输出
  • 刚刚编辑了初始帖子以添加示例(初始表格和结果)
猜你喜欢
  • 2012-10-02
  • 2020-05-27
  • 1970-01-01
  • 2013-10-19
  • 2012-12-18
  • 2018-08-24
  • 2011-01-05
  • 2016-11-13
  • 1970-01-01
相关资源
最近更新 更多