如何在没有公共字段的情况下联接2个表?

时间:2019-05-18 09:10:17

标签: sql sql-server

有2个表:

表1:名字

id | first_name 
 1 | Joey 
 7 | Ross
 17| Chandler

表2:姓氏

id | first_name
 2 | Tribbiani
 7 | Geller 
 25| Bing 

所需结果:

id | full_name
1  | Joey Tribbiani
2  | Ross Geller
3  | Chandler Bing

任务: 仅使用最简单的SQL语法编写解决方案。 禁止使用存储过程声明变量,ROW_NUMBER()RANK()函数。

我有使用ROW_NUMBER()函数的解决方案,但没有关于仅使用最简单的SQL语法解决此任务的想法。

P.S。我只是实习生,这是我关于stackoverflow的第一个问题

3 个答案:

答案 0 :(得分:2)

简单的join在这里就足够了

select * from first_names fn
join last_names ln on fn.id = ln.id - 1

但是您的问题仍然不清楚。因为这里join的基础是有关Friends系列的知识,而不是具体的逻辑...

答案 1 :(得分:1)

您必须创建一个ID才能加入表。
这可以是表格中基于ID的订单号:

select 
  f.counter id, concat(f.first_name, ' ', l.last_name) full_name
from (
  select t.*, (select count(*) from first_names where id < t.id) + 1 counter
  from first_names t
) f inner join (
 select t.*, (select count(*) from last_names where id < t.id) + 1 counter
  from last_names t
) l
on l.counter = f.counter

请参见demo
结果:

> id | full_name     
> -: | :-------------
>  1 | Joey Tribbiani
>  2 | Ross Geller   
>  3 | Chandler Bing 

答案 2 :(得分:0)

老实说,这是一个愚蠢的解决方案。 ROW_NUMBER的效率非常低,如果LEAD不允许,那么如果“不允许” ROW_NUMBER,我也不会感到惊讶。告诉您“使用最简单的SQL”的事实意味着您要使用的SQL是子查询/ CTE和ROW_NUMBER;这真的很简单。其他任何因素都会增加不必要的复杂性,并可能使查询遭受性能下降的困扰。例如,这意味着您需要对两个表进行两次扫描。与ROW_NUMBER一样在一次。

CREATE TABLE FirstNames (id int, FirstName varchar(10));
CREATE TABLE LastNames (id int, LastName varchar(10));

INSERT INTO FirstNames
VALUES(1,'Joey'),
      (7,'Ross'),
      (17,'Chandler');

INSERT INTO LastNames
VALUES (2,'Tribbiani'),
       (7,'Geller'),
       (25,'Bing');
GO
WITH CTE AS(
    SELECT FN.id,
           FN.FirstName,
           LN.LastName
    FROM FirstNames FN
        LEFT JOIN LastNames LN ON FN.id = LN.id
    UNION ALL
    SELECT LN.id,
           FN.FirstName,
           LN.LastName
    FROM LastNames LN
        LEFT JOIN FirstNames FN ON LN.id = FN.id
    WHERE FN.id IS NULL),
FullNames AS(
    SELECT C.id,
        C.FirstName,
        ISNULL(C.LastName, LEAD(C.LastName) OVER (ORDER BY id)) AS LastName
    FROM CTE C)
SELECT *
FROM FullNames FN
WHERE FN.FirstName IS NOT NULL
ORDER BY FN.id;


GO

DROP TABLE FirstNames;
DROP TABLE LastNames;

要回答给出的“任务”: “任务:仅使用最简单的SQL语法编写解决方案。禁止使用存储过程,声明变量,ROW_NUMBER()和RANK()函数。”

我的回答是下面的?

“为什么要这样做?自SQL Server 2005以来,SQL Server已经支持ROW_NUMBER 14年了。如果您不能使用ROW_NUMBER,则表明您正在使用SQL Server。 2000年,这实际上是公司的一个重大安全问题,因为2000年已经失去了将近十年的支持,像GDPR这样的法规要求公司保持其使用的技术的安全性,因此这种可能性极小见过。

如果是这种情况,那么解决方案就不是找到使用ROW_NUMBER的方法,而是让公司恢复正常运行。您可以从SQL Server 2000升级到的最新版本的SQL Server是2008;您可以从Windows Server 2008升级到最新版本。在今年7月16日也没有支持。我们需要启动并运行实例,并将现有功能尽快添加到该新服务器中,并尽快完成质量检查。这应该是最高优先级的事情。之后,我们需要将循环重复到另一个版本的SQL Server。最新的是2017年,它支持从2008年开始的迁移。

完成此操作后,我们便可以在查询中实际使用ROW_NUMBER了;提供最简单的解决方案,并使公司重返安全环境。”

有时需要挑战要求。根据经验,管理人员可能会提出一些“愚蠢”的要求,因为他们不了解该技术。当您担任IT角色时,有时您需要质疑这些需求并解释为什么该需求实际上不是一个好主意。然后,您可以帮助管理部门找到该问题的正确解决方案。归根结底,他们可能试图解决的问题可能是XY问题;排除故障的一部分将是找出X的真正含义。