Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如何获取唯一的匹配记录(参见示例)_Sql Server - Fatal编程技术网

Sql server 如何获取唯一的匹配记录(参见示例)

Sql server 如何获取唯一的匹配记录(参见示例),sql-server,Sql Server,这个例子只是为了说明这个问题,与我正在处理的实际数据完全不同,但是使用任何类似于实际数据的东西都会非常复杂 假设我有这两套: id name license ----------- ---- ----------- 1 Joe 1 2 Eric 1 3 Jane 2 4 Mike 2 id name license ----------- -------- ------

这个例子只是为了说明这个问题,与我正在处理的实际数据完全不同,但是使用任何类似于实际数据的东西都会非常复杂

假设我有这两套:

id          name license
----------- ---- -----------
1           Joe  1
2           Eric 1
3           Jane 2
4           Mike 2

id          name     license
----------- -------- -----------
11          Van #1   1
12          Van #2   1
13          Truck #1 2
14          Truck #2 2
我想为每辆车找到一个有资格驾驶它的司机。而且,由于示例许可证对于每种类型的车辆都是唯一的,驾驶卡车之类的任何事情都不能使驾驶员具备驾驶面包车的资格。因此,预期结果如下所示:

driver_id   driver_name driver_license vehicle_id  vehicle_name vehicle_license
----------- ----------- -------------- ----------- ------------ ---------------
1           Joe         1              11          Van #1       1
2           Eric        1              12          Van #2       1
3           Jane        2              13          Truck #1     2
4           Mike        2              14          Truck #2     2
我已经能够通过下面的查询得到这个结果,但是如果查询集较大,结果可能会变慢。有没有其他更好的方法获得同样的结果

select d.id driver_id
       ,d.name driver_name
       ,d.license driver_license
       ,v.id vehicle_id
       ,v.name vehicle_name
       ,v.license vehicle_license
    from (select id
               ,name
               ,license
               ,rank() over (partition by license order by id) rank_driver
            from ( values ( 1, 'Joe', 1), 
                      ( 2, 'Eric', 1), 
                      ( 3, 'Jane', 2), 
                      ( 4, 'Mike', 2) ) driver (id, name, license)) d
   left join (select id
                  ,name
                  ,license
                  ,rank() over (partition by license order by id) rank_vehicle
            from ( values ( 11, 'Van #1', 1) , 
                      ( 12, 'Van #2', 1), 
                      ( 13, 'Truck #1', 2), 
                      ( 14, 'Truck #2', 2) ) vehicle (id, name, license)) v 
on d.license = v.license and d.rank_driver = v.rank_vehicle

当您问这个问题时,如果您为表添加DDL脚本并为示例数据添加脚本,那将非常好。如果在性能方面存在问题,则需要添加适当的索引

CREATE NONCLUSTERED INDEX ix_drivers ON drivers (name) INCLUDE (license);
CREATE NONCLUSTERED INDEX ix_vehicles ON vehicles (name) INCLUDE (license);

CREATE TABLE #drivers
(
    id INT, name VARCHAR(100), license int
);

CREATE TABLE #vehicles
(
    id INT, name VARCHAR(100), license int
);

INSERT INTO #drivers 
        ( id, name, license )
VALUES
(1,           'Joe',  1),
(2,           'Eric', 1),
(3,           'Jane', 2),
(4,           'Mike', 2);

INSERT INTO #vehicles
        ( id, name, license )
VALUES
(11,          'Van #1',   1),
(12,          'Van #2',   1),
(13,          'Truck #1', 2),
(14,          'Truck #2', 2)

SELECT a.id, a.name, a.license, b.id, b.name, b.license 
FROM 
(
SELECT id, name, license, ROW_NUMBER() OVER (PARTITION BY license ORDER BY name) AS rownum
FROM #drivers
) a
JOIN
(
SELECT id, name, license, ROW_NUMBER() OVER (PARTITION BY license ORDER BY name) AS rownum
FROM #vehicles
) b 
ON a.license = b.license
AND a.rownum = b.rownum
ORDER BY 1

你的解决方案很好。我会这样写:

select d.id driver_id, d.name driver_name, d.license driver_license,
       v.id vehicle_id, v.name vehicle_name, v.license vehicle_license
from (select d.*,
             row_number() over (partition by license order by id) as rank_driver
      from drivers d
     ) d left join
     (select v.*,
             row_number() over (partition by license order by id) as rank_vehicle
      from vehicles v
     ) v 
     on d.license = v.license and d.rank_driver = v.rank_vehicle
如果您关心可伸缩性,我建议在表中使用索引:driverslicense,id和vehicleslicense,id


虽然在外部查询中避免使用*是一种很好的做法,但对于子查询来说,这是一种过分的做法——除非您生成的是一个准备好的语句或视图,其编译形式可能会持续很长时间。数据库本身将优化查询,以仅选择所需的列。在实现子查询的MySQL中不是这样,但那是另一回事。

感谢DDL语句,我倾向于在这些练习中使用from值。不过,您发布的解决方案完全相同,只是将排名更改为行号。首先,排名与行号不同。不过,我也添加了索引。我知道排名和行号不一样,但就本例而言,它们是可交换的,或者你是想说在这种情况下使用行号更好?是的,如果你有相同的驱动程序名,那么你会遇到麻烦。车辆名称也是如此。仅当名称列将包含在功能的分区/顺序部分时,它们不是。感谢您的帮助和兴趣,我同意使用select*,但我从未在SO问题中使用select*,因为有几十人抱怨它,而不是看问题;