【发布时间】:2021-12-03 05:48:14
【问题描述】:
我在 SQL Server 中有 2 个表,我想通过它们的 ID 获取所有可能的组合,即使第二个没有记录,我想知道是否有比我更好的解决方案。
我的两张桌子是:
- 拥有 10 条记录的公司(CompanyId、Tot1、Tot2)
- 具有 4 条记录的电机(MotorId、CompanyId_FK、TotSales1、TotSales2)
,这里是创建和填充它们的脚本:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Companies](
[CompanyId] [int] IDENTITY(1,1) NOT NULL,
[Tot1] [int] NOT NULL,
[Tot2] [int] NOT NULL,
CONSTRAINT [PK_Companies] PRIMARY KEY CLUSTERED
(
[CompanyId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[Motors] Script Date: 10/15/2021 9:18:31 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Motors](
[MotorId] [int] IDENTITY(1,1) NOT NULL,
[CompanyId] [int] NOT NULL,
[TotSales1] [int] NOT NULL,
[TotSales2] [int] NOT NULL,
CONSTRAINT [PK_Motors] PRIMARY KEY CLUSTERED
(
[MotorId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET IDENTITY_INSERT [dbo].[Companies] ON
GO
INSERT [dbo].[Companies] ([CompanyId], [Tot1], [Tot2]) VALUES (1, 300, 200)
GO
INSERT [dbo].[Companies] ([CompanyId], [Tot1], [Tot2]) VALUES (2, 400, 100)
GO
INSERT [dbo].[Companies] ([CompanyId], [Tot1], [Tot2]) VALUES (3, 500, 100)
GO
INSERT [dbo].[Companies] ([CompanyId], [Tot1], [Tot2]) VALUES (4, 600, 200)
GO
INSERT [dbo].[Companies] ([CompanyId], [Tot1], [Tot2]) VALUES (5, 700, 500)
GO
INSERT [dbo].[Companies] ([CompanyId], [Tot1], [Tot2]) VALUES (6, 800, 400)
GO
INSERT [dbo].[Companies] ([CompanyId], [Tot1], [Tot2]) VALUES (7, 900, 300)
GO
INSERT [dbo].[Companies] ([CompanyId], [Tot1], [Tot2]) VALUES (8, 50, 20)
GO
INSERT [dbo].[Companies] ([CompanyId], [Tot1], [Tot2]) VALUES (9, 80, 20)
GO
INSERT [dbo].[Companies] ([CompanyId], [Tot1], [Tot2]) VALUES (10, 40, 10)
GO
SET IDENTITY_INSERT [dbo].[Companies] OFF
GO
SET IDENTITY_INSERT [dbo].[Motors] ON
GO
INSERT [dbo].[Motors] ([MotorId], [CompanyId], [TotSales1], [TotSales2]) VALUES (1, 4, 35, 23)
GO
INSERT [dbo].[Motors] ([MotorId], [CompanyId], [TotSales1], [TotSales2]) VALUES (2, 5, 140, 70)
GO
INSERT [dbo].[Motors] ([MotorId], [CompanyId], [TotSales1], [TotSales2]) VALUES (3, 7, 200, 24)
GO
INSERT [dbo].[Motors] ([MotorId], [CompanyId], [TotSales1], [TotSales2]) VALUES (4, 9, 2, 1)
GO
SET IDENTITY_INSERT [dbo].[Motors] OFF
GO
ALTER TABLE [dbo].[Motors] WITH CHECK ADD CONSTRAINT [FK_Motors_Companies] FOREIGN KEY([CompanyId])
REFERENCES [dbo].[Companies] ([CompanyId])
GO
ALTER TABLE [dbo].[Motors] CHECK CONSTRAINT [FK_Motors_Companies]
GO
我需要一个包含 Motor 和 Company 的所有可能组合的列表作为结果集,即使没有销售:
| CompanyId | MotorId | Tot1 | Tot2 | TotSales1 | TotSales2 |
|---|---|---|---|---|---|
| 4 | 1 | 600 | 200 | 35 | 23 |
| 4 | 2 | 600 | 200 | NULL | NULL |
| 4 | 3 | 600 | 200 | NULL | NULL |
| 4 | 4 | 600 | 200 | NULL | NULL |
我通过 CROSS JOIN 创建了一个只有 CompanyId 和 MotorId 的 CTE,然后我以这种方式加入了另外两个:
;WITH myTable AS (
SELECT Companies.CompanyId, MotorId
FROM Companies CROSS JOIN Motors
GROUP BY Companies.CompanyId, MotorId)
SELECT myTable.*, Tot1, Tot2, TotSales1,TotSales2 FROM myTable
INNER JOIN Companies ON myTable.CompanyId = Companies.CompanyId
LEFT OUTER JOIN Motors ON myTable.CompanyId = Motors.CompanyId AND myTable.MotorId = Motors.MotorId
有没有更好的解决方案?为避免误解:我无法更改字段的顺序以将结果映射到 C# 类。
【问题讨论】:
-
提问时,您需要提供minimal reproducible example: (1) DDL 和样本数据填充,即 CREATE 表和 INSERT T-SQL 语句。 (2) 你需要做什么,即逻辑和你的代码尝试在 T-SQL 中实现它。 (3) 期望的输出,基于上述#1 中的样本数据。 (4) 您的 SQL Server 版本 (SELECT @@version;)。
-
理想情况下,您应该有一个完全独立的
Motor表,而这个Motors表应该真正称为CompanyMotor,然后您只需交叉加入前两个,然后左加入最后一个。 -
@YitzhakKhabinsky 我的帖子现在正确吗?
-
@Charlieface 是的,就像我对 CTE 所做的那样,对吧?
-
理想情况下它应该是一个真实的物理表。您当前的设计有些缺陷
标签: sql sql-server tsql cartesian-product sql-server-2019