将ID附加到多次联接的SQL表上的字段吗?

问题描述

我有两个桌子

PersonId | Device1 | Device2 | Device3
---------+---------+---------+--------
    1         10       20         30

设备

DeviceId | Name | Description | PicklingCoefficient
---------+------+-------------+--------------------
   10       AA     Whatever             1
   20       BB     Who knows           -1
   30       CC     Blah blah           100

一个查询将前三个查询连接到后三个查询:

select p.PersonId,d1.*,d2.*,d3.* from People p     
  left join Device d1 on d1.DeviceId = p.Device1
  left join Device d2 on d2.DeviceId = p.Device2
  left join Device d3 on d3.DeviceId = p.Device3

这将产生格式为(人+设备+设备+设备)的表头,其中Device表字段仅重复3次:

PersonId | Device1 | Device2 | Device3 | DeviceId | Name | Description | PicklingCoefficient | DeviceId | Name | Description | PicklingCoefficient | DeviceId | Name | Description | PicklingCoefficient

从技术上讲,我可以构建一个字符串生成器,以便在提交查询之前为每个d(n)表生成一些唯一的名称,但是有没有一种方法可以简化它?

可能是在查询的第一行后面添加一些内容,以提供以下格式(人员+设备1 +设备2 +设备3):

PersonId | Device1 | Device2 | Device3 | DeviceId1 | Name1 | Description1 | PicklingCoefficient1 | DeviceId2 | Name2 | Description2 | PicklingCoefficient2 | DeviceId3 | Name3 | Description3 | PicklingCoefficient3

我希望这样的事情能起作用:

select p.PersonId,d1.* + '1',d2.* + '2',d3.* + '3' from People p 

解决方法

这里的真正问题是设计不规范。您似乎在这里有多对多的关系,这意味着您实际需要做的是规范化设计。

您应该拥有另一个处理多对多关系的表,而不是让设备具有三个不同列的people。简单来说,您的表格如下:

CREATE TABLE dbo.People (PersonID int IDENTITY PRIMARY KEY,[Name] nvarchar(50)); --Overly simplified
GO
CREATE TABLE dbo.Device (DeviceID int IDENTITY PRIMARY KEY,[Name] char(2),[Description] varchar (50),PicklingCoefficient smallint);
GO
CREATE TABLE dbo.PersonDevice (PersonID int,DeviceID int);

ALTER TABLE dbo.PersonDevice ADD CONSTARINT PersonDevice_PK PRIMARY KEY(PersonID,DeviceID);

ALTER TABLE dbo.PersonDevice ADD CONSTRAINT PersonDevice_PersonFK FOREIGN KEY (PersonID) REFERENCES dbo.People (PersonID);
ALTER TABLE dbo.PersonDevice ADD CONSTRAINT PersonDevice_DeviceFK FOREIGN KEY (DeviceID) REFERENCES dbo.Device (DeviceID);
GO

然后,您将INSERT像这样:

INSERT INTO dbo.People ([Name])
VALUES(N'Bob'),(N'Jayne');

INSERT INTO dbo.Device ([Name],[Description],PicklingCoefficient)
VALUES('AA','Whatever',1),('BB','Who knows',-1),('CC','Blah blah',100);
GO
--Then the device relationship
INSERT INTO dbo.PersonDevice(PersonID,DeviceID)
VALUES(1,(1,2),3),(2,3);

那么您就不需要多个联接,因为您只有2个联接,并且没有重复的列:

SELECT *
FROM dbo.People P
     JOIN dbo.PersonDevice PD ON P.PersonID = PD.PersonID
     JOIN dbo.Device D ON PD.DeviceID = D.DeviceID;
,

我建议您取消透视并将数据放在单独的行上

select p.PersonId,v.device_number,d.*
from People p  cross apply
     (values (1,p.Device1),p.Device2),(3,p.Device3)
     ) v(device_number,device) left join
     Device d
     on d.DeviceId = v.device_number
order by p.PersonId,v.device_number;

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...