选择可能具有相同值的行的多个实例
Posted
技术标签:
【中文标题】选择可能具有相同值的行的多个实例【英文标题】:SELECT multiple instances of a row where they might have the same value 【发布时间】:2020-10-15 13:43:59 【问题描述】:我希望能够选择一些客户详细信息,然后选择客户地址详细信息,现在这些客户地址详细信息还包括以前的地址,有些客户最多有 3 个地址(包括以前的),有些只有一个。
我想从客户数据库中选择客户,然后从地址数据库中选择客户地址,并在同一行上为每个客户加载最多 3 个地址。
客户数据库:
| name | value | num |SecondName| Date |
| James | HEX124 | 1 | Carl | 11022020 |
| Jack | JEU836 | 4 | Smith | 19042020 |
| Mandy | GER234 | 33 | Jones | 09042020 |
地址数据库
| Address | value | PostCode |
| 1 Smith street | HEX124 | LN18HB |
| 12 fellow garden | GER234 | LN18JL |
| 8 Long street | HEX124 | FF23F2 |
| 8 Big road | HEX124 | FWF4GW |
| 89 Kings avenue | GER234 | HH29DD |
| Roadhouse Cottage | JEU836 | FK28DD |
客户数据库中的“值”列是客户的唯一值,该值也用于地址数据库中,最多可为该特定客户分配 3 个地址
下面是我的 SQL:
SELECT c.name, c.value, c.num, c.secondname, c.date,
a.address, a.value, a.postcode,
a2.address, a2.value, a2.postcode,
a3.address, a3.value, a3.postcode
FROM Customers c
INNER JOIN Address a ON a.value = c.value. //first address
INNER JOIN Address a2 ON a2.value = c.value //second address
INNER JOIN Address a3 ON a3.value = c.value //third address
这将为每个客户返回尽可能多的行,与他们拥有的地址一样多,并将为他们重复相同的地址 3 次:
结果:
| James | HEX124 | 1 | Carl | 11022020 | 1 Smith street | HEX124 | LN18HB | 1 Smith street | HEX124 | LN18HB | 1 Smith street | HEX124 | LN18HB |
| James | HEX124 | 1 | Carl | 11022020 | 8 Long street | HEX124 | FF23F2 | 8 Long street | HEX124 | FF23F2 | 8 Long street | HEX124 | FF23F2 |
如您所见,上面的结果只是为客户重复相同的地址,James 将有 3 行,Mandy 2 行,Jack 1 行(每个地址 1 行)
所以我尝试添加它,希望它会读取不同的地址,或者如果它们没有 3 个地址,则返回空值:
WHERE a.address <> a2.address //Saying the addresses must not be the same, but this loads nothing when I run the SQL
AND a.address <> a3.address
AND a2.address <> a3.address
但这会返回 0 个结果
想要的结果:
| James | HEX124 | 1 | Carl | 11022020 | 1 Smith street | HEX124 | LN18HB | 8 Long street | HEX124 | FF23F2 | 8 Big road | HEX124 | FWF4GW |
| Jack | JEU836 | 4 | Smith | 19042020 | Roadhouse Cottage | JEU836 | FK28DD |
| Mandy | GER234 | 33 | Jones | 09042020 | 12 fellow garden | GER234 | LN18JL | 89 Kings avenue | GER234 | HH29DD |
正如您在我想要的结果中看到的那样,我将每个客户加载一次,他们以前的所有地址都放在他们列的末尾,一些客户将有 1、2 或 3 个地址,
【问题讨论】:
如果有 4 个(或更多)地址,什么决定应该返回哪 3 个地址? 【参考方案1】:似乎你在这里追求的是一个支点,但在 ROW_NUMBER
的值上。我假设您有某种始终升序的地址键,因此您可以确定最近的地址。我还使用了交叉表(条件聚合),因为它比 PIVOT
运算符的限制要小得多:
WITH RNs AS(
SELECT c.[name],
c.[value],
c.num,
c.secondname,
c.[date],
a.address,
a.[value] AS addressvalue,
a.postcode,
ROW_NUMBER() OVER (PARTITION BY c.[value] ORDER BY a.idcolumn DESC) AS RN
FROM dbo.Customer c
JOIN dbo.Address a ON a.[value] = c.[value])
SELECT R.[name],
R.[value],
R.num,
R.secondname,
R.[date],
MAX(CASE R.RN WHEN 1 THEN R.address END) AS address1,
MAX(CASE R.RN WHEN 1 THEN R.addressvalue END) AS addressvalue1,
MAX(CASE R.RN WHEN 1 THEN R.postcode END) AS postcode1,
MAX(CASE R.RN WHEN 2 THEN R.address END) AS address2,
MAX(CASE R.RN WHEN 2 THEN R.addressvalue END) AS addressvalue2,
MAX(CASE R.RN WHEN 2 THEN R.postcode END) AS postcode2,
MAX(CASE R.RN WHEN 3 THEN R.address END) AS address3,
MAX(CASE R.RN WHEN 3 THEN R.addressvalue END) AS addressvalue3,
MAX(CASE R.RN WHEN 3 THEN R.postcode END) AS postcode3
FROM RNs R
GROUP BY c.[name],
c.[value],
c.num,
c.secondname,
c.[date];
【讨论】:
【参考方案2】:You can utilize Row_Number(). ie:
with addresses (AddrNo, [Value], Address, PostCode) as
(
Select row_number() over (partition by [value] order by Address, PostCode),
[Value], Address, PostCode
)
SELECT c.name, c.value, c.num, c.secondname, c.date,
max(case when a.AddrNo=1 then a.address end) as Address1,
max(case when a.AddrNo=1 then a.[Value] end) as Value1,
max(case when a.AddrNo=1 then a.PostCode end) as PostCode1,
max(case when a.AddrNo=2 then a.address end) as Address2,
max(case when a.AddrNo=2 then a.[Value] end) as Value2,
max(case when a.AddrNo=2 then a.PostCode end) as PostCode2,
max(case when a.AddrNo=3 then a.address end) as Address3,
max(case when a.AddrNo=3 then a.[Value] end) as Value3,
max(case when a.AddrNo=3 then a.PostCode end) as PostCode3
FROM Customers c
INNER JOIN Addresses a ON a.[value] = c.[value]
group by c.name, c.value, c.num, c.secondname, c.date;
注意:这只是其中一种方法。还有其他方法可能更容易。
【讨论】:
以上是关于选择可能具有相同值的行的多个实例的主要内容,如果未能解决你的问题,请参考以下文章