使用 COUNT() 左连接的 SQL

Posted

技术标签:

【中文标题】使用 COUNT() 左连接的 SQL【英文标题】:SQL to LEFT JOIN with COUNT() 【发布时间】:2017-11-22 11:44:14 【问题描述】:

我正在处理 SQL,但遇到以下错误:

窗口函数只能出现在 SELECT 或 ORDER BY 子句中

发生错误是因为我的代码中有COUNT()。我知道这是一个讨厌的代码,但有点工作......

因此它尝试通过tblAmpReport.WEB_IDWEB_ID 加入tblAmpReport 表。 WEB_IB 是用下面这个讨厌的代码计算的。但是,COUNT() 似乎引起了问题。有谁知道克服这个问题的更好方法?

left join tblAmplianceReport
    on ISNULL(tblWebIDLegacy.WebProductStyleID,
                case
                when count(tblCrystalBeauty.STOCK_ON_HAND) over(partition by tblCrystalBeauty.ITEM_PARENT) > 1
                    then case
                        when count(tblCrystalBeauty.STOCK_ON_HAND) over(partition by tblCrystalBeauty.ITEM_PARENT+'_'+cast(tblCrystalBeauty.RETAIL_PRICE as varchar(10))) = count(tblCrystalBeauty.STOCK_ON_HAND) over(partition by tblCrystalBeauty.ITEM_PARENT)
                            then tblCrystalBeauty.ITEM_PARENT+'_'+tblCrystalBeauty.ITEM
                        else case
                                when count(tblCrystalBeauty.STOCK_ON_HAND) over(partition by tblCrystalBeauty.ITEM_PARENT) > 4
                                    then tblCrystalBeauty.ITEM_PARENT+'_'+tblCrystalBeauty.ITEM
                                else tblCrystalBeauty.ITEM_PARENT
                                end
                        end
                else tblCrystalBeauty.ITEM_PARENT
                end) = tblAmplianceReport.WEB_ID

完整的 SQL:

select tblCrystalBeauty.GROUP_NO
      ,tblCrystalBeauty.GROUP_NAME
      ,tblCrystalBeauty.DEPT_NAME
      ,tblCrystalBeauty.CLASS_NAME
      ,tblCrystalBeauty.BRAND
      ,tblCrystalBeauty.MAIN_SEASON
      ,tblCrystalBeauty.SUB_SEASON
      ,tblCrystalBeauty.SUB_NAME
      ,tblCrystalBeauty.PRODUCT_TYPE
      ,tblCrystalBeauty.PL_CYCLE
      ,tblCrystalBeauty.ITEM as ITEM
      ,cast(tblCrystalBeauty.ITEM as int) as ITEM_VALUE
      ,tblCrystalBeauty.ITEM_DESC
      ,tblCrystalBeauty.ITEM_PARENT as ITEM_PARENT
      ,cast(tblCrystalBeauty.ITEM_PARENT as int) as ITEM_PARENT_VALUE
      ,tblCrystalBeauty.***
      ,tblCrystalBeauty.SUPP_COLOUR
      ,tblCrystalBeauty._COLOUR
      ,tblCrystalBeauty.SIZE_1
      ,tblCrystalBeauty.SIZE_2
      ,tblCrystalBeauty.RETAIL_PRICE
      ,tblCrystalBeauty.EAN as EAN
      ,cast(tblCrystalBeauty.EAN as bigint) as EAN_VALUE
      ,tblCrystalBeauty.WH_SOH
      ,tblCrystalBeauty.STOCK_ON_HAND
      ,tblCrystalBeauty.CREATE_DATETIME
      ,ISNULL(tblWebIDLegacy.WebProductStyleID,
                             case
                               when count(tblCrystalBeauty.STOCK_ON_HAND) over(partition by tblCrystalBeauty.ITEM_PARENT) > 1
                                 then case
                                        when count(tblCrystalBeauty.STOCK_ON_HAND) over(partition by tblCrystalBeauty.ITEM_PARENT+'_'+cast(tblCrystalBeauty.RETAIL_PRICE as varchar(10))) = count(tblCrystalBeauty.STOCK_ON_HAND) over(partition by tblCrystalBeauty.ITEM_PARENT)
                                          then tblCrystalBeauty.ITEM_PARENT+'_'+tblCrystalBeauty.ITEM
                                        else case
                                               when count(tblCrystalBeauty.STOCK_ON_HAND) over(partition by tblCrystalBeauty.ITEM_PARENT) > 4
                                                 then tblCrystalBeauty.ITEM_PARENT+'_'+tblCrystalBeauty.ITEM
                                               else tblCrystalBeauty.ITEM_PARENT
                                             end
                                      end
                               else tblCrystalBeauty.ITEM_PARENT
                             end) as "WEB_ID"
      ,case
         when row_number() over(partition by ISNULL(ISNULL(tblODIPublished.WEB_PROD_STYLE_ID,tblWebIDLegacy.WebProductStyleID),tblCrystalBeauty.ITEM_PARENT) order by
              (
                                                                                                                                                                      select 1
              )) > 1
           then 0
         else 1
       end as OPTION_COUNT
      ,case
         when sum(tblCrystalBeauty.STOCK_ON_HAND) over(partition by tblCrystalBeauty.ITEM_PARENT) > 0
           then 'YES'
         else 'NO'
       end as IN_STOCK
      ,sum(tblCrystalBeauty.STOCK_ON_HAND) over(partition by tblCrystalBeauty.ITEM_PARENT) as STYLE_SOH
      ,case
         when case
                when tblCrystalBeauty.PL_CYCLE = 'Discontinued'
                     or tblCrystalBeauty.PL_CYCLE = 'Discontinued'
                  then 'NO'
                else 'YES'
              end = 'YES'
              and case
                    when charindex('Dum',tblCrystalBeauty.CLASS_NAME) > 0
                      then 'NO'
                    else 'YES'
                  end = 'YES'
              and tblBrands.WEB_ALLOWED = 'Yes'
           then 1
         else 0
       end as CONGRUENCY
      ,ISNULL(tblBrands.CUTOUTS,'DN') as USE_COUTOUTS
      ,'' as MARKED_FOR_WEB_WEB_ID
      ,case
         when tblMarkedForWeb.CREATE_DATETIME is not null
           then 'YES'
         else 'NO'
       end as MARKED_FOR_WEB_SKU
      ,cast(tblMarkedForWeb.CREATE_DATETIME as datetime) as MFWD
      ,case
         when tblODIPublished.SKU_B4N_UPLOAD_MODIFIED_DATE is not null
           then 'YES'
         else 'NO'
       end as PUBLISHED
      ,cast(tblODIPublished.SKU_B4N_UPLOAD_MODIFIED_DATE as datetime) as PD
      ,case
         when tblODIPublished.SKU_B4N_UPLOAD_MODIFIED_DATE is not null
           then 1
         else 0
       end as PUBLISHED_COUNT
      ,case
         when case
                when tblBeautyCopy.COPY_COMPLETE_DATE is not null
                  then 'YES'
                else 'NO'
              end = 'YES'
              and case
                    when tblAmplianceReport.IMAGE_DATE_UPLOADED is not null
                      then 'YES'
                    else 'NO'
                  end = 'YES'
              and case
                    when tblODIPublished.SKU_B4N_UPLOAD_MODIFIED_DATE is not null
                      then 'YES'
                    else 'NO'
                  end = 'NO'
           then 'YES'
         else 'NO'
       end as READY_TO_UPLOAD
      ,case
         when tblAmplianceReport.IMAGE_DATE_UPLOADED is not null
           then 'YES'
         else 'NO'
       end as IMG_UPLOADED
      ,tblAmplianceReport.IMAGE_DATE_UPLOADED as IUD
      ,tblBeautyCopy.COPY_COMPLETE_DATE
      ,case
         when tblBeautyCopy.COPY_COMPLETE_DATE is not null
           then 'YES'
         else 'NO'
       end as COPY_COMP
      ,tblBeautyCopy.COPY_COMPLETE_DATE as CACD
      ,case
         when tblBeautyCopy.COPY_COMPLETE_DATE is not null
           then 'YES'
         else 'NO'
       end as CAT_COMP
      ,case
         when tblTransfers.CREATE_DATE is not null
           then 'YES'
         else 'NO'
       end as TRANSFERRED_TO_PACKSHOT
      ,tblTransfers.CREATE_DATE as TTPD
      ,case
         when tblImageOrder.DATE is not null
           then 'YES'
         else 'NO'
       end as IMAGE_ORDER
      ,tblImageOrder.DATE as IOD
      ,MV_REP_PUBLISHED_WCID_LEVEL.ONLINE_FLAG as DW_ONLINE_FLAG_WCID
      ,MV_REP_PUBLISHED_WCID_LEVEL.PUBLISHED as DW_PUBLISHED_FLAG_WCID
      ,MV_REP_PUBLISHED_SKU_LEVEL.ONLINE_FLAG as DW_ONLINE_FLAG_SKU
      ,MV_REP_PUBLISHED_SKU_LEVEL.PUBLISHED as DW_PUBLISHED_FLAG_SKU
      ,ISNULL(tblDepartment.DEPARTMENT,'DN') as DEPARTMENT
from tblCrystalBeauty
    left join tblODIPublished
        on tblCrystalBeauty.ITEM = tblODIPublished.SKU
    left join tblWebIDLegacy
        on tblCrystalBeauty.ITEM = tblWebIDLegacy.SkuId
    left join tblAmplianceReport
        on ISNULL(tblWebIDLegacy.WebProductStyleID,
                                 case
                                   when count(tblCrystalBeauty.STOCK_ON_HAND) over(partition by tblCrystalBeauty.ITEM_PARENT) > 1
                                     then case
                                            when count(tblCrystalBeauty.STOCK_ON_HAND) over(partition by tblCrystalBeauty.ITEM_PARENT+'_'+cast(tblCrystalBeauty.RETAIL_PRICE as varchar(10))) = count(tblCrystalBeauty.STOCK_ON_HAND) over(partition by tblCrystalBeauty.ITEM_PARENT)
                                              then tblCrystalBeauty.ITEM_PARENT+'_'+tblCrystalBeauty.ITEM
                                            else case
                                                   when count(tblCrystalBeauty.STOCK_ON_HAND) over(partition by tblCrystalBeauty.ITEM_PARENT) > 4
                                                     then tblCrystalBeauty.ITEM_PARENT+'_'+tblCrystalBeauty.ITEM
                                                   else tblCrystalBeauty.ITEM_PARENT
                                                 end
                                          end
                                   else tblCrystalBeauty.ITEM_PARENT
                                 end) = tblAmplianceReport.WEB_ID
    left join tblBeautyCopy
        on tblCrystalBeauty.ITEM_PARENT = tblBeautyCopy.RETEK_PARENT
    left join tblMarkedForWeb
        on tblCrystalBeauty.ITEM = tblMarkedForWeb.ITEM
    left join tblImageOrder
        on tblCrystalBeauty.ITEM_PARENT = tblImageOrder.ITEM_PARENT
    left join tblBrands
        on cast(tblCrystalBeauty.GROUP_NO as varchar(10))+'_'+tblCrystalBeauty.BRAND = tblBrands.PRIMARY_KEY
    left join MV_REP_PUBLISHED_SKU_LEVEL
        on tblCrystalBeauty.ITEM = MV_REP_PUBLISHED_SKU_LEVEL.SKU
    left join MV_REP_PUBLISHED_WCID_LEVEL
        on ISNULL(ISNULL(tblODIPublished.WEB_PROD_STYLE_ID,tblWebIDLegacy.WebProductStyleID),
                                                                                           case
                                                                                             when charindex('Oxfo',tblCrystalBeauty.SIZE_1) = 1
                                                                                               then cast(tblCrystalBeauty.ITEM_PARENT as varchar(10))+'OX'
                                                                                             else tblCrystalBeauty.ITEM_PARENT
                                                                                           end) = MV_REP_PUBLISHED_WCID_LEVEL.PRODUCT_ID
    left join tblTransfers
        on tblCrystalBeauty.ITEM = tblTransfers.ITEM
    left join tblDepartment
        on cast(tblCrystalBeauty.GROUP_NO as varchar(10))+'_'+tblCrystalBeauty.GROUP_NAME = tblDepartment.GROUP_NAME
where tblCrystalBeauty.ITEM_PARENT is not null
      and tblCrystalBeauty.PL_CYCLE != 'Discontinued'
order by WEB_ID desc;

【问题讨论】:

请包括您的整个格式化查询,以及示例输入和输出。 mysqlsql-server 有什么关系? HI @TimBiegeleisen,这是一个从 10 个表中返回 54 列的大型查询。代码如下: 在我看来,问题不在于计数,而在于计数之后的 OVER。这就是这里的窗口函数。您可能想尝试分离为子查询甚至 CTE。 Windowed functions can only appear in the SELECT or ORDER BY clauses的可能重复 【参考方案1】:

我相信您可以通过使用 APPLY 运算符来解决这个问题。在这里,您可以参考您的其他表,只需将您的“加入”部分移动到 where 子句。

在您的情况下,它应该类似于:

cross apply (


        select ISNULL(tblWebIDLegacy.WebProductStyleID,
                                 case
                                   when count(tblCrystalBeauty.STOCK_ON_HAND) over(partition by tblCrystalBeauty.ITEM_PARENT) > 1
                                     then case
                                            when count(tblCrystalBeauty.STOCK_ON_HAND) over(partition by tblCrystalBeauty.ITEM_PARENT+'_'+cast(tblCrystalBeauty.RETAIL_PRICE as varchar(10))) = count(tblCrystalBeauty.STOCK_ON_HAND) over(partition by tblCrystalBeauty.ITEM_PARENT)
                                              then tblCrystalBeauty.ITEM_PARENT+'_'+tblCrystalBeauty.ITEM
                                            else case
                                                   when count(tblCrystalBeauty.STOCK_ON_HAND) over(partition by tblCrystalBeauty.ITEM_PARENT) > 4
                                                     then tblCrystalBeauty.ITEM_PARENT+'_'+tblCrystalBeauty.ITEM
                                                   else tblCrystalBeauty.ITEM_PARENT
                                                 end
                                          end
                                   else tblCrystalBeauty.ITEM_PARENT
                                 end) as joincolumn
                                 --Add columns you need at the main select
                                 from tblAmplianceReport)

                                 -- add this to your where clause at the end
                                 where joincolumn = tblAmplianceReport.WEB_ID

【讨论】:

以上是关于使用 COUNT() 左连接的 SQL的主要内容,如果未能解决你的问题,请参考以下文章

具有多个左连接的 SQL 重复行

sql - 左连接 - 计数

MySql 左连接几个表后怎么进行统计?count(*)、sum(..)

SQL 将 MAX 应用于具有非空行的左连接表

Access97 左连接选择

表上的左连接 COUNT