我有一个由 sku,store,和期间键入的销售表。由此,我需要一个返回包含今年和去年信息的记录的查询。
以下查询背后的逻辑是:
我的问题是去年的结果不是全部金额。我的结果就好像我正在进行LEFT JOIN,而不是从“LAST YEAR”表中返回所有结果。
其他细节:
下面的代码已经简化了一些...我不是很担心语法,而是更多关于LOGIC。如果有人有任何想法,或者知道我的逻辑中存在可能的缺陷,我全都耳朵!提前谢谢!
WITH lastYear AS (
SELECT
spsku "sku",
spstor "store",
sum(spales) "sales_ly"
FROM SALES
WHERE spyypp BETWEEN 201205 AND 201205
GROUP BY spstor, spsku
)
SELECT
Sales_report.spstor "store",
sum(spales) "bom_retail",
sum(LY."sales_ly") "sales_ly"
FROM SALES Sales_report
FULL OUTER JOIN lastYear LY ON LY."sku" = spsku AND LY."store" = spstor
WHERE spyypp BETWEEN 201305 AND 201305
GROUP BY spstor
答案 0 :(得分:1)
条款WHERE spyypp BETWEEN 201305 AND 201305
具有强制您加入INNER JOIN的结果,因为在加入完成后执行。
为了达到您想要的效果,您必须将此子句移动到这样的ON条件中,以便在>>连接之前应用该子句:
WITH lastYear AS (
SELECT
spsku "sku",
spstor "store",
sum(spales) "sales_ly"
FROM SALES
WHERE spyypp BETWEEN 201205 AND 201205
GROUP BY spstor, spsku
)
SELECT
Sales_report.spstor "store",
sum(spales) "bom_retail",
sum(LY."sales_ly") "sales_ly"
FROM SALES Sales_report
FULL OUTER JOIN lastYear LY
ON LY."sku" = spsku
AND LY."store" = spstor
AND spyypp BETWEEN 201305 AND 201305
GROUP BY spstor
或者,在某些情况下提供更清晰的代码,同时使LAST_YEAR和THIS_YEAR公用表表达式如下:
WITH
lastYear AS (
SELECT
spsku "sku",
spstor "store",
sum(spales) "sales_ly"
FROM SALES
WHERE spyypp BETWEEN 201205 AND 201205
GROUP BY spstor, spsku
),
this year as (
SELECT
spsku "sku",
spstor "store",
sum(spales) "sales_ly"
FROM SALES
WHERE spyypp BETWEEN 201305 AND 201305
GROUP BY spstor, spsku
)
SELECT
TY.spstor "store",
sum(TY.spales) "bom_retail",
sum(LY."sales_ly") "sales_ly"
FROM this year TY
FULL OUTER JOIN lastYear LY
ON LY."sku" = TY.sku
AND LY."store" = TY.stor
答案 1 :(得分:0)
似乎存在多个问题。这个谓词:
WHERE spyypp BETWEEN 201305 AND 201305
可能正在消除一些“外连接”行。对于spyypp,这些行将具有NULL。 (spsku的分组有点奇怪,但实际上这可能不是问题,你只需要获得单独的行...总共有一个匹配的spsku,另一行它们不是,但那些所有人都会崩溃购买GROUP BY,所以我不明白这一点。
如果你想使用公用表表达式,我想你想使用两个,并对这些结果集进行全外连接。我使用的函数为非匹配选取非NULL值,ISNULL函数对此很方便。
WITH lastYear AS
(
SELECT
spsku,
spstor,
sum(spales) AS sales_ly
FROM SALES
WHERE spyypp BETWEEN 201205 AND 201205
GROUP BY spstor, spsku
)
, thisYear AS (
SELECT
spsku,
spstor,
SUM(spales) AS sales_ty
FROM SALES
WHERE spyypp BETWEEN 201305 AND 201305
GROUP BY spstor, spsku
)
SELECT ISNULL(thisYear.spstor,lastYear.spstor) AS "store"
, SUM(TY.sales_ty) AS "bom_retail"
, SUM(LY.sales_ly) AS "sales_ly"
FROM thisYear TY
FULL
OUTER
JOIN lastYear LY
ON LY.spsku = TY.spsku
AND LY.store = TY.store
GROUP
BY ISNULL(thisYear.spstor,lastYear.spstor)
如果这是你所追求的结果集,那似乎是一大堆不必要的噪音。如果您不关心返回的spsku及其完整的外连接,那么此查询将返回等效的结果集:
SELECT r.spstor AS "store"
, SUM(CASE WHEN r.spyypp BETWEEN 201305 AND 201305 THEN r.spsales END) AS "bom_retail"
, SUM(CASE WHEN r.spyypp BETWEEN 201205 AND 201205 THEN r.spsales END) AS "sales_ly"
FROM SALES r
WHERE r.spyypp BETWEEN 201305 AND 201305
OR r.spyypp BETWEEN 201205 AND 201205
GROUP
BY r.spstor
这里的“技巧”是使用条件测试,以确定是否应该在SUM中包含销售额。
如果这实际上是针对MySQL(而不是SQL Server),那么我会这样写:
SELECT r.spstor AS `store`
, SUM(IF(r.spyypp BETWEEN 201305 AND 201305,r.spsales,NULL)) AS `bom_retail`
, SUM(IF(r.spyypp BETWEEN 201205 AND 201205,r.spsales,NULL)) AS `sales_ly`
FROM SALES r
WHERE r.spyypp BETWEEN 201305 AND 201305
OR r.spyypp BETWEEN 201205 AND 201205
GROUP
BY r.spstor
答案 2 :(得分:0)
谢谢大家的建议。我确实重组了SQL,以使今年和去年都嵌套在一个with子句中。除了我在主要条款中选择/分组为sku之外,我所看到的致命缺陷是仅存在于去年数据集中的sku's不被包括在内。
为了解决这个问题,我使用了下面的代码。我用TY / LY销售的占位符分别构建了数据集。然后我执行了一个UNION来组合表(TY / LY存储在不同的列和不同的行中)。我把所有这些都塞进了一个子查询中。因为我在对数据进行求和(按非求和字段分组),这会折叠所有行,以便以正确的格式正确反映。
WITH lastYear AS (
SELECT sku, store, sum(sales) "sales_ly"
FROM DWHLIB.SLSSUMPD
WHERE spyypp BETWEEN 201205 AND 201205
GROUP BY store, sku
),
thisYear AS (
SELECT spsku sku, store, sum(sales) "sales"
FROM DWHLIB.SLSSUMPD
WHERE spyypp BETWEEN 201305 AND 201305
GROUP BY store, sku
)
SELECT sum(AY."sales"), sum(AY."sales_ly"), AY."store"
FROM (
SELECT sum(TY."sales") "sales", 0 "sales_ly", TY."store"
FROM thisYear TY GROUP BY TY."store"
UNION ALL
SELECT 0 "sales", sum(LY."sales_ly") "sales_ly", LY."store"
FROM lastYear LY
GROUP BY LY."store"
) AY
GROUP BY "store"