【问题标题】:Two separate queries; one needs to count rows from the other两个单独的查询;一个需要从另一个计算行
【发布时间】:2018-01-19 02:10:21
【问题描述】:

我有两个单独的查询。一个用于详细信息文件,另一个用于结尾/拖车文件(我也有一个头文件,但与这个问题无关)。我必须将它们分开,因为它们会返回不同的列。

问题是我的详细文件有 13,470 行,但是当我在辅助查询(预告文件)中进行计数时,我得到 13,207 行。原因是少数商品具有多个与主要商品 ID 关联的辅助 ID。

如果我不使用SELECT DISTINCT,我可以获得相同的计数,但它会返回 25,250 行。我需要在我的详细信息文件中保留重复项。

详细信息查询很长,但请理解,尽管几乎所有记录都是唯一的,但有些主要项目 ID 看似重复,只是因为次要项目 ID 可能与主要项目 ID 有几个不同的值.

我已阅读以下文章,但似乎无法让其中任何一篇发挥作用。请注意,我使用的是 Microsoft SQL Server 2012 而不是 MySQL,但我确实将 MySQL 的概念应用到了我在其中一篇文章中解释的需求:

Multiple COUNT() for multiple conditions in one query (MySQL)

SUM of grouped COUNT in SQL Query

Counting Values based on distinct values from another Column

同样,我想根据我在详细信息文件中指定的所有条件(数十列和 13,470 行)进行计数。我的预告片文件只有两列和一行。一个用于识别它是结尾/预告片文件,另一个用于显示详细信息文件应返回的记录数。

这是我的“只是尝试看看这是否有效或是否在正确的路径上”查询(但它没有):

    SELECT DISTINCT
    CAST('TRL' AS VARCHAR(3)) AS RECID,
    (CASE 
        WHEN COUNT(I2.VNDRITNM) > COUNT(DISTINCT I2.ITEMNMBR)
        THEN COUNT(I2.VNDRITNM)
        WHEN COUNT(I2.VNDRITNM) = COUNT(DISTINCT I2.ITEMNMBR)
        THEN COUNT(I2.ITEMNMBR)
        ELSE COUNT(DISTINCT I2.ITEMNMBR)
    END) AS TOTREC
    FROM Inv00101 I
    JOIN Inv00102 I2 ON I2.ITEMNMBR = I.ITEMNMBR
    JOIN ItemUnit I3 ON I3.ITEMNMBR = I.ITEMNMBR
    LEFT OUTER JOIN prodmaster D ON D.itemid = I.ITEMNMBR
    LEFT OUTER JOIN productinfo I4 ON I4.ITEMNMBR = I.ITEMNMBR
    WHERE (ITMDESC LIKE '%ART%' OR ITMDESC LIKE '%CRAFT%')

这将返回 25,250 行。

当然CASE 声明是错误的,但我只是想探索一下它作为一个选项。有谁知道如何让我的查询同步?

再次:

  • 微软 SQL Server 2012
  • 1个头文件(作品)
  • 1 个详细文件(作品)
  • 1 个预告文件(未按预期工作)

使用CASE 声明的预告片结果:

  | RECID | TOTREC |
--------------------
1 | TRL   | 25250  |

仅在其中一列上计算 DISTINCT 的预告片结果:

  | RECID | TOTREC |
--------------------
1 | TRL   | 13207  |

寻找:

  | RECID | TOTREC |
--------------------
1 | TRL   | 13470  |

任何建议将不胜感激。谢谢!

编辑

这是详细文件查询,但我删除了不相关的列;我执行了这个查询,它的工作原理与未编辑的查询相同,所以这应该足以说明:

SELECT DISTINCT
    RTRIM(CAST('DTL' AS VARCHAR(3))) AS RECID,
    RTRIM(CAST('12345' AS VARCHAR(10))) AS COMPANY,
    RTRIM(CAST(CASE 
                WHEN I2.VNDITNUM = ''
                THEN 'BLANK'
                ELSE I2.VNDITNUM END AS VARCHAR(20))) AS VNDITEM,
    RTRIM(CAST(I.ITEMNMBR AS VARCHAR(20))) AS NUMITEM,
    RTRIM(CAST(I.ITEMDESC AS VARCHAR(60))) AS ITMDESC,
    RTRIM(CAST(CASE 
          WHEN I.INACTIVE = '0' 
          THEN 'A' 
          WHEN I.INACTIVE = '1' 
          THEN 'I' END AS VARCHAR(1))) AS STATUS
FROM Inv00101 I
JOIN Inv00102 I2 ON I2.ITEMNMBR = I.ITEMNMBR
JOIN ItemUnit I3 ON I3.ITEMNMBR = I.ITEMNMBR
LEFT OUTER JOIN prodmaster D ON D.itemid = I.ITEMNMBR
LEFT OUTER JOIN productinfo I4 ON I4.ITEMNMBR = I.ITEMNMBR
WHERE (ITMDESC LIKE '%ART%' OR ITMDESC LIKE '%CRAFT%')

请注意,ITEMNMBR 是主要的内部 ID,而 VNDITNUM 是供应商/供应商 ID,我称之为辅助 ID。有时,VNDITNUM 有多个产品的唯一主要内部 ID 记录。

正常结果如下:

  | RECID | COMPANY | VNDITEM | NUMITEM | ITMDESC | STATUS |
------------------------------------------------------------
1 | DTL   | 12345   | 011223  | 100234  | Game    | A      |
2 | DTL   | 12345   | 015992  | 104722  | Picture | A      |

但这里有一个例子说明它可能如何复制:

  | RECID | COMPANY | VNDITEM | NUMITEM | ITMDESC | STATUS |
------------------------------------------------------------
1 | DTL   | 12345   | 029445  | 109777  | Book A  | A      |
2 | DTL   | 12345   | 029478  | 109777  | Book A  | A      |

【问题讨论】:

  • 您是从这些查询中创建实际文件吗?或者只是结果集。
  • @jderekc:你自己回答了这个问题。您说您在“详细信息”查询中使用secondary ID,但您没有在“预告片”查询中使用它。如果secondary ID 是“详细信息”查询的选择标准的一部分,那么从逻辑上讲,您需要在“预告片”查询中使用secondary ID 才能获得相同的计数。
  • 您可以做的第二件事:如果您的 'Trailer' 查询总是只返回 1 条记录,您可以在您的 'Detail' 查询之后使用 tsql 函数 @@rowcount。然后您可以将实际的行数放入您的“预告片”中。您需要声明一个整数变量,如:DECLARE @rc as integer; 然后在您的“详细”查询之后分配@rc 行数:set @rc = @@rowcount; 然后在您的 Trailer 查询中,您可以在您想要行数的地方使用@rc 变量。
  • 这些查询结果集将被导出到唯一的文件中。另外,如果您查看我的案例陈述,我会尝试包含两个 ID 以进行比较,但我的逻辑不正确。
  • @jderekc:您可能需要向我们展示您的“详细信息”查询,以便我们了解您的primary IDsecondary ID 的实际使用情况。如果您的“预告片”查询正在删除您的 secondary ID 记录,那么您的逻辑问题就在那里。

标签: sql sql-server sql-server-2012 count


【解决方案1】:

我找到了一种使用派生表执行此操作的方法,这样我仍然可以将查询分开并使用 SSIS 填充单独的平面文件(如果没有UNIONs 的一个查询具有多个选择语句,则无法做到这一点) .感谢大家帮助我到达那里!非常感谢您的建议。

这是我使用的:

SELECT 
    CAST('TRL' AS VARCHAR(3)) AS RECID,
    COUNT(TotalRows) AS TOTREC 
FROM (SELECT DISTINCT
    RTRIM(CAST(CASE 
            WHEN I2.VNDITNUM = ''
            THEN 'BLANK'
            ELSE I2.VNDITNUM END AS VARCHAR(20))) AS VNDITEM,
    RTRIM(CAST(I.ITEMNMBR AS VARCHAR(20))) AS NUMITEM,
    @@ROWCOUNT AS TotalRows,
    I.ITMDESC
    FROM Inv00101 I
    JOIN Inv00102 I2 ON I2.ITEMNMBR = I.ITEMNMBR
    JOIN ItemUnit I3 ON I3.ITEMNMBR = I.ITEMNMBR
    LEFT OUTER JOIN prodmaster D ON D.itemid = I.ITEMNMBR
    LEFT OUTER JOIN productinfo I4 ON I4.ITEMNMBR = I.ITEMNMBR
    WHERE (ITMDESC LIKE '%ART%' OR ITMDESC LIKE '%CRAFT%')

【讨论】:

    【解决方案2】:

    如果您的“预告片”查询只返回 1 条记录...那么您可以尝试使用 tsql 函数 @@recordcount

    像这样:

    -- Declare an integer variable
    DECLARE @rc as integer;
    
    -- Your Detail query
    SELECT
       IDont
       ,CareWhat
       ,TheDetailLogicIs
    FROM
       Inv00101 as i
       JOIN WhoKnowsWhat as idk ON i.ITEMNMBR = idk.ITEMNMBR
    WHERE 
       Who = Cares;
    
    -- Assign your row count variable with the row count of the last executed query.
    SET @rc = @@rowcount;
    
    -- Your new Trailer query
    SELECT
       'TRL' AS [RECID]
       ,@rc AS [TOTREC];
    

    这还有一个额外的好处,那就是为您提供您感兴趣的实际查询的行数。此外,您不必执行可能很耗时的重复逻辑(尤其是当您的 Detail 查询如您想象的那样复杂时)。

    希望有帮助:)

    【讨论】:

    • 这确实有效,谢谢!我还不确定如何将其导出到多个文件,但我还没有尝试过。
    猜你喜欢
    • 2020-05-13
    • 1970-01-01
    • 1970-01-01
    • 2018-12-28
    • 1970-01-01
    • 2013-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多