【问题标题】:SQL- get data from two tables in different columns without using unionsSQL-从不同列中的两个表中获取数据而不使用联合
【发布时间】:2013-06-17 13:18:01
【问题描述】:

我有一张桌子STOCK,看起来像这样:

PRODUCT   SALES_CODE  STOCK_1    STOCK_2    STOCK_3
-----------------------------------------------------
A         6-10        0          1          2

有很多 STOCK_X 存储桶,但为简单起见,我已将其排除在外。

现在我有另一张桌子SIZE_GRID

SALES_CODE    SIZE_1   SIZE_2   SIZE_3
--------------------------------------
6-10          6        8        10

正如您可能已经猜到的那样,这些是特定产品的现有库存,按尺寸排列。

我需要从第一个表中获取 STOCK 值,并从第二个表中获取大小。 最初,我在做以下事情

SELECT
  STOCK.PRODUCT,
  SIZE_GRID.SIZE_1,
  STOCK.STOCK_1
FROM
  STOCK
INNER JOIN
  SIZE_GRID ON
  SIZE_GRID.SALES_CODE = STOCK.SALES_CODE
UNION ALL
SELECT
  STOCK.PRODUCT,
  SIZE_GRID.SIZE_2,
  STOCK.STOCK_2
FROM
  STOCK
INNER JOIN
  SIZE_GRID ON
  SIZE_GRID.SALES_CODE = STOCK.SALES_CODE
UNION ALL
SELECT
  STOCK.PRODUCT,
  SIZE_GRID.SIZE_3,
  STOCK.STOCK_3
FROM
  STOCK
INNER JOIN
  SIZE_GRID ON
  SIZE_GRID.SALES_CODE = STOCK.SALES_CODE

我有大约 40 个 STOCK_X 需要检索,所以如果有更简单的方法可以做到这一点,那么徘徊?最好我想使用纯 SQL 而不是 UDF/SP。

http://sqlfiddle.com/#!6/f323e

【问题讨论】:

  • 上述方法封装到视图中除了繁琐之外,还有什么问题?

标签: sql sql-server


【解决方案1】:

如果您使用的是 SQL Server 2008 或更高版本,您可以尝试以下方法(找到here):

SELECT
  STOCK.PRODUCT,
  X.SIZE,
  X.STOCK
FROM
  STOCK
INNER JOIN
  SIZE_GRID ON
  SIZE_GRID.SALES_CODE = STOCK.SALES_CODE
CROSS APPLY (
  VALUES
    (SIZE_GRID.SIZE_1, STOCK.STOCK_1),
    (SIZE_GRID.SIZE_2, STOCK.STOCK_2),
    (SIZE_GRID.SIZE_3, STOCK.STOCK_3)
) X (SIZE, STOCK)
;

只需稍加调整,您就可以使其在 SQL Server 2005 中也能正常工作:

SELECT
  STOCK.PRODUCT,
  X.SIZE,
  X.STOCK
FROM
  STOCK
INNER JOIN
  SIZE_GRID ON
  SIZE_GRID.SALES_CODE = STOCK.SALES_CODE
CROSS APPLY (
  SELECT SIZE_GRID.SIZE_1, STOCK.STOCK_1
  UNION ALL
  SELECT SIZE_GRID.SIZE_2, STOCK.STOCK_2
  UNION ALL
  SELECT SIZE_GRID.SIZE_3, STOCK.STOCK_3
) X (SIZE, STOCK)
;

但是,如果您使用的是更早的版本,这可能会有所帮助:

SELECT
  STOCK.PRODUCT,
  SIZE  = CASE X.N
            WHEN 1 THEN SIZE_GRID.SIZE_1
            WHEN 2 THEN SIZE_GRID.SIZE_2
            WHEN 3 THEN SIZE_GRID.SIZE_3
          END,
  STOCK = CASE X.N
            WHEN 1 THEN STOCK.STOCK_1
            WHEN 2 THEN STOCK.STOCK_2
            WHEN 3 THEN STOCK.STOCK_3
          END,
FROM
  STOCK
INNER JOIN
  SIZE_GRID ON
  SIZE_GRID.SALES_CODE = STOCK.SALES_CODE
CROSS JOIN (
  SELECT 1
  UNION ALL
  SELECT 2
  UNION ALL
  SELECT 3
) X (N)
;

虽然最后两个选项使用 UNION ALL,但它们仅组合单行,而不是整个子集

【讨论】:

  • 效果很好。它不仅干净得多(从 600 行到 100 行),而且比 union 快得多(从 7 秒到
【解决方案2】:

考虑规范化表格。而不是重复的列:

PRODUCT   SALES_CODE  STOCK_1    STOCK_2    STOCK_3

使用规范化表格:

PRODUCT   SALES_CODE   STOCK_NO   STOCK

SIZE_GRID 表也是如此:

SALES_CODE    SIZE_NO   SIZE

现在您无需列出 40 列即可查询:

select  *
from    STOCK s
join    SIZE_GRID sg
on      sg.SALES_CODE = s.SALES_CODE
        and sg.SIZE_NO = s.STOCK_NO

【讨论】:

  • 不是一个选项。这是一个非常古老的遗留系统。
  • @Lock 考虑规范化。我认为这是实现这一目标的唯一方法,最好是更好的方法。
  • 如上所述不可能。
【解决方案3】:

以下是您可以使用的一些替代方案:

  • 分别执行每个 SQL 并在程序中合并和排序结果集
  • 加入表格。
  • 使用标量子查询。

选择
从 Table_1 q1 中选择 col1、col2、col3,

选择 col1, col2, col3 来自 Table_2 q2 来自 dual;

  • 尝试使用带有 NVL 函数的 FULL OUTER JOIN 的 UNION:建议这比 UNION 运算符的性能更快。
select
    empno,
    ename,
     nvl(dept.deptno,emp.deptno) deptno, dname from emp
full outer join 
dept 
on
    (emp.deptno = dept.deptno) 
order by 1,2,3,4;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-05
    • 2021-06-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多