我的表看起来有点像这样:
Table name: products
ID PRODUCT_ID TYPE PRICE ...
1 111 computer xxx
2 222 book xx
3 333 computer xxxx
----------------------------------------------------------------
Table name: products_computer
ID PRODUCT_ID CPU RAM ....
1 111 amd 16
2 333 intel 8
----------------------------------------------------------------
Table name: products_book
ID PRODUCT_ID AUTHOR YEAR_PUBLISHED ....
1 222 Stephen King xxxx
正如您所看到的,在表products
中,每个产品都列有它们共有的列(如价格),其他表包含该产品类型的特定信息。
现在假设我们要列出按价格排序的每个类型的产品,并且还要在查询中包含products_*
表的特定信息,而不是手动进行第二次查询以便检索信息。
虽然我几乎没有使用数据库和SQL,但是我的经验不足会遇到各种陷阱,试图连接字符串以构建products_*
的{{1}}表名,或者创建一个映射{的{中间表' {1}}实际表名的值,我在后面的文档中发现它只是不起作用,试图将列/行值“绑定”为表名。
是否有任何“技巧”使这项工作(在1个查询中包含所有内容),或者我是否真的必须在我的代码中手动进行第二次查询?
答案 0 :(得分:3)
如果我理解正确,那么您需要来自products
表的所有列及其products_computer
和products_book
表中的相应信息(如果有)。
如果是这个场景,那么我认为你需要的只是多个LEFT JOIN
SQL语句
SQL语句
SELECT products.product_id, type , price, cpu, ram, author, year_published
FROM products
LEFT JOIN products_computer ON products.product_id = products_computer.product_id
LEFT JOIN products_book ON products.product_id = products_book.product_id
ORDER BY price
<强>输出强>
答案 1 :(得分:2)
使用UNION
语句可以实现这一点。
SELECT
products.ID AS ID, products.PRODUCT_ID AS PRODUCT_ID, products.PRICE AS PRICE, products_computer.CPU AS CPU, products_computer.RAM AS RAM,
null as AUTHOR, null as YEAR_PUBLISHED
FROM products_computer
JOIN products ON products_computer.PRODUCT_ID = products.PRODUCT_ID
UNION
SELECT
products.ID AS ID, products.PRODUCT_ID AS PRODUCT_ID, products.PRICE AS PRICE, null as CPU, null as RAM,
products_book.AUTHOR AS AUTHOR, products_book.YEAR_PUBLISHED AS YEAR_PUBLISHED
FROM products_book
JOIN products ON products_book.PRODUCT_ID = products.PRODUCT_ID
ORDER BY PRICE
两个单独的查询将合并为一个更大的查询。为此,每个SELECT
语句中选择的列必须相同。请注意我为其他表中的列SELECT
编辑空值的方式。
每个SELECT
个人也会根据常见的PRODUCT_ID列加入products
。价格包含在内,最后有ORDER BY语句按PRICE排序。
这是查询的输出:
根据@ Zero的评论,可以将查询存储为视图。作为一次性操作,请将查询作为视图定义执行:
CREATE VIEW vw_products_all AS
SELECT products.ID AS ID,
products.PRODUCT_ID AS PRODUCT_ID,
products.PRICE AS PRICE,
products_computer.CPU AS CPU,
products_computer.RAM AS RAM,
NULL AS AUTHOR,
NULL AS YEAR_PUBLISHED
FROM products_computer
JOIN products
ON products_computer.PRODUCT_ID = products.PRODUCT_ID
UNION
SELECT products.ID AS ID,
products.PRODUCT_ID AS PRODUCT_ID,
products.PRICE AS PRICE,
NULL AS CPU,
NULL AS RAM,
products_book.AUTHOR AS AUTHOR,
products_book.YEAR_PUBLISHED AS YEAR_PUBLISHED
FROM products_book
JOIN products
ON products_book.PRODUCT_ID = products.PRODUCT_ID
ORDER BY PRICE;
...之后可以通过以下方式访问数据:
SELECT * FROM vw_products_all
......或更明确地(良好做法):
SELECT ID,
PRODUCT_ID,
PRICE,
CPU,
RAM,
AUTHOR,
YEAR_PUBLISHED
FROM vw_products_all
输出与原始查询的输出相同。
答案 2 :(得分:-1)
According to Larry Wall your instinct to be too lazy to write the code yourself is right。生成将所有这些表组合在一起的视图相当容易。试试这个:
DECLARE @SQL NVARCHAR(MAX) = 'CREATE VIEW vw_products_all AS ' +
SUBSTRING((
SELECT [text()] = REPLACE(REPLACE(REPLACE(
' UNION ALL {1}SELECT P.id, P.PRODUCT_ID, P.Name, {2} FROM dbo.products AS P INNER JOIN dbo.{0} AS PS ON P.PRODUCT_ID = PS.PRODUCT_ID'
, '{0}', QUOTENAME(O.name))
, '{1}', CHAR(10))
, '{2}', SUBSTRING((
SELECT [text()] = ', ' + ISNULL(QUOTENAME(C_this.name), 'NULL as ' + QUOTENAME(C_all.name))
FROM sys.columns AS C_all
LEFT JOIN sys.columns AS C_this
ON O.object_id = C_this.object_id
AND C_all.name = C_this.name
WHERE OBJECT_NAME(C_all.object_id) LIKE 'product[_]%'
AND c_all.name NOT IN ('PRODUCT_ID', 'ID')
ORDER BY C_all.name
FOR XML PATH('')
), 2, 10000000000000))
FROM sys.objects AS O
WHERE name LIKE 'product[_]%'
FOR XML PATH('')
), 11, 1000000000000)
SELECT @SQL