我在SQL Server 2000中有一个表,我试图以特定方式查询。显示此信息的最佳方式是使用示例数据。
看哪,[Addresses]
:
Name Street City State
--------------------------------------------------------
Bob 123 Fake Street Peoria IL
Bob 234 Other Street Fargo ND
Jim 345 Main Street St Louis MO
这实际上是实际表结构的简化示例。桌子的结构完全超出了我的控制范围。我需要一个查询,每个名称将返回一个地址。哪个地址无关紧要,只有一个地址。结果可能是这样的:
Name Street City State
--------------------------------------------------------
Bob 123 Fake Street Peoria IL
Jim 345 Main Street St Louis MO
我发现了一个类似的问题here,但由于我无法访问CROSS APPLY
,并且在每列上调用MIN()
会混合使用虽然我不关心返回哪条记录,但它必须是一条完整的行,而不是不同行的混合。
更改表格结构的建议对我没有帮助。我同意这个表格很糟糕(这比这里显示的更糟糕),但这是我无法改变的主要ERP数据库的一部分。
此表中有大约3000条记录。没有主键。
有什么想法吗?
答案 0 :(得分:4)
嗯,这会给你很糟糕的表现,但我认为它会起作用
SELECT t.Name, t.Street, t.City, t.State
FROM table t
INNER JOIN (
SELECT m.Name, MIN(m.Street + ';' + m.City + ';' + m.State) AS comb
FROM table m
GROUP BY m.Name
) x
ON x.Name = t.Name
AND x.comb = t.Street + ';' + t.City + ';' + t.State
答案 1 :(得分:3)
使用临时表或表变量,并在其中选择不同的名称列表。然后使用该结构为原始表中的每个记录选择每个不同名称的前1个。
答案 2 :(得分:3)
如果你可以使用临时表:
select * -- Create and populate temp table
into #Addresses
from Addresses
alter table #Addresses add PK int identity(1, 1) primary key
select Name, Street, City, State
-- Explicitly name columns here to not return the PK
from #Addresses A
where not exists
(select *
from #Addresses B
where B.Name = A.Name
and A.PK > B.PK)
对于更大的表格,此解决方案不可取。
答案 3 :(得分:2)
select distinct Name , street,city,state
from table t1 where street =
(select min(street) from table t2 where t2.name = t1.name)
答案 4 :(得分:2)
选择姓名,街道,城市,州FROM( 选择姓名,街道,城市,州, ROW_NUMBER()OVER(按名称分区按名称排序)ASn 来自表)AS t 在哪里rn = 1
答案 5 :(得分:1)
临时表解决方案如下
CREATE Table #Addresses
(
MyId int IDENTITY(1,1),
[Name] NVARCHAR(50),
Street NVARCHAR(50),
City NVARCHAR(50),
State NVARCHAR(50)
)
INSERT INTO #Addresses ([Name], Street, City, State) SELECT [Name], Street, City, State FROM Addresses
SELECT
Addresses1.[Name],
Addresses1.Street,
Addresses1.City,
Addresses1.State
FROM
#Addresses Addresses1
WHERE
Addresses1.MyId =
(
SELECT
MIN(MyId)
FROM
#Addresses Addresses2
WHERE
Addresses2.[Name] = Addresses1.[Name]
)
DROP TABLE #Addresses
答案 6 :(得分:1)
这很丑陋,但听起来你的困境也很丑陋......所以这就是......
select name,
(select top 1 street from [Addresses] a1 where a1.name = a0.name) as street,
(select top 1 city from [Addresses] a2 where a2.name = a0.name) as city,
(select top 1 state from [Addresses] a3 where a3.name = a0.name) as state
from (select distinct name from [Addresses]) as a0
答案 7 :(得分:1)
我认为这是基于游标的解决方案的理想选择。我使用游标已经很久了,我不会尝试编写T-SQL,但这就是想法:
答案 8 :(得分:0)
对上述内容稍加修改应该有效。
SELECT Name, Street, City, State
FROM table t
INNER JOIN (
SELECT Name, MIN(Street) AS Street
FROM table m
GROUP BY Name
) x
ON x.Name = t.Name AND x.Street = t.Street
如果您拥有相同的街道但其他信息不同(例如使用拼写错误),现在这将无效。
OR更完整的哈希将包括所有字段(但您可能有太多的性能):
SELECT Name, Street, City, State
FROM table t
INNER JOIN (
SELECT Name, MIN(Street + '|' + City + '|' + State) AS key
FROM table m
GROUP BY Name
) x
ON x.Name = t.Name
AND x.key = Street + '|' + City + '|' + State
答案 9 :(得分:0)
考虑到你的限制,我认为你不能这样做。您可以提取这些字段的不同组合。但如果有人用同一地址拼写Bob和Bobb,你最终会得到两条记录。 [GIGO]你是正确的,任何分组(在所有字段上分组 - 相当于DISTINCT)都会混合行。您没有为每个客户提供唯一标识符太糟糕了。
您可以将查询嵌套在一起,以便为每个名称选择前1并将所有这些加在一起。
答案 10 :(得分:0)
SELECT name,
( SELECT TOP 1 street, city, state
FROM addresses b
WHERE a.name = b.name )
FROM addresses a
GROUP BY name
答案 11 :(得分:0)
SELECT name, street, address, state
FROM
(SELECT name, street, address, state,
DENSE_RANK() OVER (PARTITION BY name ORDER BY street DESC) AS r
FROM tbl) AS t
WHERE r = 1;
答案 12 :(得分:0)
还有另一种方式:
-- build a sample table
DECLARE @T TABLE (Name VARCHAR(50),Street VARCHAR(50),City VARCHAR(50),State VARCHAR(50))
INSERT INTO @T
SELECT 'Bob','123 Fake Street','Peoria','IL' UNION
SELECT 'Bob','234 Other Street','Fargo','ND' UNION
SELECT 'Jim','345 Main Street','St Louis','MO' UNION
SELECT 'Fred','234 Other Street','Fargo','ND'
-- here is all you do to get the unique record
SELECT * FROM @T a WHERE (SELECT COUNT(*) FROM @T b WHERE a.Name = b.name and a.street <= b.street) = 1
答案 13 :(得分:0)
select c.*, b.* from companies c left outer join
(SELECT *,
ROW_NUMBER()
OVER(PARTITION BY FKID ORDER BY PKId) AS Seq
FROM Contacts) b on b.FKID = c.PKID and b.Seq = 1