Sql 计算要从行值联接的表名
我有一些看起来有点像这样的表格:Sql 计算要从行值联接的表名,sql,sqlite,Sql,Sqlite,我有一些看起来有点像这样的表格: Table name: products ID PRODUCT_ID TYPE PRICE ... 1 111 computer xxx 2 222 book xx 3 333 computer xxxx -------------------------------------------
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.TYPE
值映射到实际表名的“中间表”时遇到了各种陷阱,我在后面的文档中发现,尝试将列/行值“绑定”为表名根本不起作用
有没有什么“技巧”可以让这项工作正常进行(所有内容都在一个查询中),或者我真的必须在代码中手动进行第二个查询?这可以通过语句实现
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
s也基于公共产品ID列连接回products
。价格包括在内,最后有一个按价格排序的声明
这是查询的输出:
根据@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
。。。或者更明确地说(良好实践):
输出与原始查询的输出相同。如果我理解正确,那么您需要产品
表中的所有列,以及产品计算机
和产品手册
表中的相应信息(如果有)
如果是这种情况,那么我认为这里只需要多个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
输出
。生成一个将所有这些表放在一起的视图相当容易。试试这个:
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
在你的例子中,我真的无法理解产品是如何按价格订购的。而且,这使我写出了所有的列和具体的产品*
表格,其中的内容远远超过了我在问题中的缩小版。这可能会成为某个查询的怪物,而不是迟早。@Slyps您可以将查询作为“视图”存储在数据库本身中。“视图”不包含任何实际数据(仅包含查询),但可以像普通表一样使用它。这个view
确实很有趣,但它在为这种情况创建查询字符串的大小和工作量问题上并没有真正的帮助。如果有50种以上的产品类型(因此有50种以上的product.*
tables),该怎么办。我无法想象这在SQL pros的世界中会是一个好的实践(与在迭代产品表的结果时创建第二个查询获取特定产品的结果相比)@Slyps这是真的。但这要追溯到应用程序设计。您需要的是一种将两个子表中的值与一个公共父表相结合的方法,并列出每个子表中的所有数据。上述解决方案可以做到这一点。根本问题的背景被省略了。该问题要求“列出每种产品,与价格所订购的产品类型无关,并在查询中包括产品表的具体信息”。上述方法当然与每个表的具体实现密切相关。@CJBS是的,我知道并同意。我并不是说你的回答不是对我问题的有效回答,我只是想输入我的想法来澄清我的问题,因为我可能已经描述了不清楚的部分。作为这个问题的未来读者的一个提示,可能会有一个想法。当然,如果在我放弃等待之前,你的答案仍然是唯一的,那么我显然会接受它,即使这不是我所希望的。我为你的努力感到抱歉,我应该说我在寻找一个sqlite解决方案,而不是仅仅标记它。OP表明他使用的是sqlite,而不是SQL Server。从所有答案来看,这似乎是一个需要最少的工作量和维护,同时提供想要的结果。+1这是一个更优雅的解决方案。当我没有返回到products
表时,我最初沿着UNION
路径,但忽略了价格排序。当需要对price
进行排序时,显然将两个表连接回products
更简单。定义视图以使用此查询的选项仍然适用。
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