如何删除笛卡尔连接

How to remove the Cartesian Join

我有两个 table,其结构类似于以下 2 table。 姓名:

ID     | FirstName | LastName
__________________________
123     Akshay     kumar
123     Salman     khan
123     Johnny      lever
123     Tom           Cruise

城市:

ID     | City
___________
123     Pune

现在当我运行下面的查询时:

Select N.*,C.* from Name N,City C where C.ID=N.ID and N.ID=123; 

ID     | FirstName | LastName | ID     | City 
_____________________________________________
123     Akshay     kumar             123     Pune
123     Salman     khan               123     Pune
123     Johnny      lever               123     Pune
123     Tom           Cruise            123     Pune

Pune 重复了 4 次。而我想要如下输出:

ID     | FirstName | LastName | ID     | City 
_____________________________________________
123     Akshay     kumar             123     Pune
123     Salman     khan               
123     Johnny      lever               
123     Tom           Cruise   

姓名和城市 Table 数据之间没有关系,除了 ID Coumn。 此外,对于相同的 ID,名称 table 的条目数不一定要多于城市 Table 的条目数。 对于相同的 ID,城市 Table 也可以比名称 Table 拥有更多的行。(所以 Left Join 将不起作用) 请大家帮忙。

这是通常会在您的表示层中处理的要求,例如PHP,或任何正在使用您的数据库的工具。也就是说,我们实际上可以使用 ROW_NUMBER:

来处理您的要求
WITH cte AS (
    SELECT n.FirstName, n.LastName, c.ID, c.City,
        ROW_NUMBER() OVER (PARTITION BY c.ID, c.City ORDER BY n.LastName, n.FirstName) rn
    FROM Name n
    INNER JOIN City c ON c.ID = n.ID
    WHERE n.ID = 123
)

SELECT ID, FirstName, LastName,
    CASE WHEN rn = 1 THEN ID END AS ID,
    CASE WHEN rn = 1 THEN City END AS City
FROM cte
ORDER BY
    ID,
    LastName,
    FirstName;

您不是要删除笛卡尔积。

您实际上是想在报告中添加 "break"。对于 Oracle,请执行以下操作:

break on city

MySql,你运气不好。如果没有一些重要的编码,它就没有这样的结构。看到这个答案:.

对于其他报告工具,技术会有所不同,但请理解,您实际上是在问报告问题,而不是 SQL 问题,并且您正在寻找的报告结构是 "break" 有时称为 "control break".

您可以使用row_number解析函数如下:

select n.id, n.firstname, n.lastname, c.id, c.city, 
(select t.*, row_number() over (partition by id order by t.firstname) as rn  from name t) n
left join
(select t.*, row_number() over (partition by id order by t.city) as rn  from city t) c
on n.id = c.id and n.rn = c.rn
order by n.id, n.rn