需要Tricky sql查询,查找子查询的总和

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了需要Tricky sql查询,查找子查询的总和相关的知识,希望对你有一定的参考价值。

我的数据库的相关部分如下(MS Visio,我知道我很可怜:D):Description?

我需要提取一个包含类别中所有项目以及包的列表。所以我必须使用UNIONUNION的第一部分供您参考(因为它在SELECT的第二部分设置了UNION的数据格式;请注意?表示参数在node-mysql中的位置):

SELECT `ID`, `Name`, `Description`, 
       `PictureID`, `SellingPrice`,
       `Cost`, 0 AS `Bundle` 
FROM `Item` 
WHERE `CategoryID`=? AND 
`ID` IN ( 
         SELECT `ItemID` 
         FROM `Stock` 
         WHERE `CityID`=? 
         AND `IsLimitless`=1 OR `Quantity`>0
        ) 

所以我想把我的Bundles呈现为好像它们也是项目,所有相同的字段等。

我的尝试:

SELECT `ID`, `Name`, `Description`, `PictureID`, 
      (
       SELECT SUM( // Here SQL indicates a syntax problem
                  SELECT `ItemAmount`*`PriceModifier`*(
                                         SELECT `SellingPrice` 
                                         FROM `Item` 
                                         WHERE `ID`=`BundleItem`.`ItemID`
                                         ) 
                   FROM `BundleItem` WHERE `BundleID`=`Bundle`.`ID`
                 )
      ) AS `SellingPrice`,
      (
        SELECT SUM(
                   SELECT `ItemAmount`*(
                                        SELECT `Cost` 
                                        FROM `Item` 
                                        WHERE `ID`=`BundleItem`.`ItemID`
                                       )
                    FROM `BundleItem` WHERE `BundleID`=`Bundle`.`ID`
                  )
      ) AS `Cost`, 
      1 AS `Bundle`
FROM `Bundle` 
WHERE `ID` IN (
               SELECT `BundleID` 
               FROM `BundleCategory` 
               WHERE `CategoryID`=?
              )
//No need to check bundles for stock due to business logic

我有一个微弱的想法,我太复杂了,但遗憾的是我不能把手指放在它上面。

我们非常欢迎任何建议,并提前感谢您抽出宝贵的时间。 <3

样本数据:

Fields of no interest like "Description"/"PictureID"/"SupplierID" will be omitted
for the relevant parts to fit on screen

**Bundle**
ID  Name            Description             PictureID
1   Valentine Pack  Blah-blah tasty buy me  imgur link in text

**Item**
ID  Name               SellingPrice  Cost  CategoryID
1   Movie Ticket       10            2     24
2   Box of Chocolates  5             1     4
3   Teddy Bear         15            3     2
4   Roses              10            4     8

**Stock**
ItemID  CityID  Quantity  IsLimitLess 
1       1       25        false
1       2       11        false
2       1       84        false
3       1       33        false
4       1       1         true
4       3       1         true

**BundleItem**
BundleID  ItemID  ItemAmount  PriceModifier
1         1       2           1.25
1         2       1           1
1         3       1           1
1         4       5           0.75

**BundleCategory** (bundle for marketing reasons can appear in different
categories depending on its contents)
BundleID  CategoryID
1         4 //Sweets
1         2 //Toys
1         8 //Flowers

期望的输出:(用于搜索CityID 1,CategoryID 8,Flowers)

ID  Name    (Descr/PicID)    SellingPrice Cost         Bundle

4   Roses                    10           4            false

1   Valentine Pack           82.5         28           true
                           /*2*10*1.25+   2*2+  <movie
                             1*1*5+       1*1+  <chocolate
                             1*1*15+      3*1+  <teddy bear
                             5*0.75*10    5*4   <roses */

用户建议的解决方案根据@ drakin8564的建议,我试过了

SELECT `ID`, `Name`, `Description`, `PictureID`, 
      (
       SELECT SUM(( 
                  SELECT `ItemAmount`*`PriceModifier`*(
                                         SELECT `SellingPrice` 
                                         FROM `Item` 
                                         WHERE `ID`=`BundleItem`.`ItemID`
                                         ) 
                   FROM `BundleItem` WHERE `BundleID`=`Bundle`.`ID`
                        ))
      ) AS `SellingPrice`,
      (
        SELECT SUM((
                   SELECT `ItemAmount`*(
                                        SELECT `Cost` 
                                        FROM `Item` 
                                        WHERE `ID`=`BundleItem`.`ItemID`
                                       )
                    FROM `BundleItem` WHERE `BundleID`=`Bundle`.`ID`
                  ))
      ) AS `Cost`, 
      1 AS `Bundle`
FROM `Bundle` 
WHERE `ID` IN (
               SELECT `BundleID` 
               FROM `BundleCategory` 
               WHERE `CategoryID`=8
              )

返回

(1242): Subquery returns more than 1 row. 

即使我尝试SELECT SUM((SELECT ID FROM Item)),也会发生这种情况。奇怪的。我评论了关于它们有多好用的其他解决方案。我感谢所有参加此活动的人。 <3

答案

看起来你有一些语法问题。您的代码使用了一些更改。查看查询中的注释以获取详细信

http://sqlfiddle.com/#!9/ee0725/16

SELECT `ID`, `Name`, `Description`, `PictureID`, 
                  (SELECT SUM(`ItemAmount`*`PriceModifier`*( -- changed order of SELECT and SUM; removed extra SELECT; fixed Parens
                                         SELECT `SellingPrice` 
                                         FROM `Item` 
                                         WHERE `ID`=`BundleItem`.`ItemID`
                                         ))
                   FROM `BundleItem` WHERE `BundleID`=`Bundle`.`ID`)
       AS `SellingPrice`,
                   (SELECT SUM(`ItemAmount`*( -- changed order of SELECT and SUM; removed extra SELECT; fixed Parens
                                        SELECT `Cost` 
                                        FROM `Item` 
                                        WHERE `ID`=`BundleItem`.`ItemID`
                                       ))
                    FROM `BundleItem` WHERE `BundleID`=`Bundle`.`ID`)
       AS `Cost`, 
      1 AS `Bundle`
FROM `Bundle` 
WHERE `ID` IN (
               SELECT `BundleID` 
               FROM `BundleCategory` 
               WHERE `CategoryID`=8
              );
另一答案

这样的事情应该有效

SELECT tb.`ID`, MAX(tb.`Name`), MAX(tb.`Description`), MAX(tb.`PictureID`), 
            SUM(`ItemAmount`*`PriceModifier`*`SellingPrice`) AS `SellingPrice`,
            SUM(`ItemAmount`*`Cost`) AS `Cost`, 
            1 AS `Bundle`
FROM `Bundle` tb 
JOIN `BundleItem` tbi on tb.ID=tbi.BundleID 
JOIN `Item` ti on tbi.ItemID=ti.ID
WHERE tb.`ID` IN (
               SELECT `BundleID` 
               FROM `BundleCategory` 
               WHERE `CategoryID`=?
              )
GROUP BY tb.ID
//No need to check bundles for stock due to business logic
另一答案

您的语法错误是因为您的子查询未包含在()中。以下示例。

这将失败:

SELECT SUM(SELECT 1);

这将有效:

SELECT SUM((SELECT 1));
另一答案

假设#1:所有项目必须在城市中有足够的库存才能在该城市中提供捆绑。 (有关如何删除此业务规则,请参阅查询注释)

在样本数据中,在任何城市都没有完全有库存的捆绑 - 为了解决这个问题,我将CityID = 1中的ItemID = 4从“1”更改为“5”。这创建了您想要的输出。

假设#2:Stock.Quantity = 0是允许的。

此解决方案生成的查询结果包含物料或捆绑库存的每个城市和类别的所有物料和捆绑。底部的where子句根据原始请求将其过滤为CityID = 1和Category = 8。

注意:您可以将下面的解决方案和架构粘贴到www.sqlfiddle.com并查看结果。

更新固定BundleCategory加入。

select * from (
select 
    Stock.CityID,
    Item.CategoryID,
    Item.ID, 
    Item.Name, 
    Item.Description, 
    Item.SellingPrice, 
    Item.Cost,
    'false' as Bundle 
  from Item
  inner join Stock on Stock.ItemID = Item.ID
  where IFNULL(Stock.Quantity,0) > 0 -- remove this to show out of stock items
 union
  select 
    BundleSummary.CityID,
    BundleCategory.CategoryID,
    Bundle.ID, 
    Bundle.Name, 
    Bundle.Description, 
    BundleSummary.SellingPrice as SellingPrice,
    BundleSummary.Cost as Cost,
    'true' as Bundle 
  from Bundle 
    inner join (
      select
          BundleItem.BundleID, 
          City.CityID,
          MIN(IF(IFNULL(Stock.Quantity, 0) < BundleItem.ItemAmount, 0, 1)) as InStock,
          SUM(Item.SellingPrice * BundleItem.ItemAmount * BundleItem.PriceModifier) as SellingPrice,
          SUM(Item.Cost * BundleItem.ItemAmount) as Cost
        from BundleItem
          inner join Item on Item.ID = BundleItem.ItemID
          inner join (select distinct CityID from Stock where CityID IS NOT NULL) as City on 1=1
          left join Stock on Stock.ItemID = Item.ID and Stock.CityID = City.CityID
        group by BundleItem.BundleID, City.CityID
      ) as BundleSummary on BundleSummary.BundleID = Bundle.ID
    inner join BundleCategory on BundleCategory.BundleID = Bundle.ID
    where BundleSummary.InStock = 1 -- remove this to show out of stock bundles
) as qry1
where CityID=1 and CategoryID=8;

我还生成了一个脚本来创建数据库模式并使用示例数据填充它。认为这可能对使用此解决方案调查自己的问题的任何人都有帮助。

架构

create table Item (
  ID int,
  Name varchar(255),
  Description varchar(255),
  PictureID int,
  SellingPrice DECIMAL(12,4),
  Cost DECIMAL(12,4),
  SupplierID int,
  CategoryID int
);
insert into Item values (1, 'Movie Ticket', '', NULL, 10, 2, NULL, 24);
insert into Item values (2, 'Box of Chocolates', '', NULL, 5, 1, NULL, 4);
insert into Item values (3, 'Teddy Bear', '', NULL, 15, 3, NULL, 2);
insert into Item values (4, 'Roses', '', NULL, 10, 4, NULL, 8);

create table Bundle (
  ID int,
  Name varchar(255),
  Description varchar(255),
  PictureID int
);
insert into Bundle values (1, 'Valentine Pack', 'Blah-blah tasty buy me', NULL);

create table Stock (
  ItemID int,
  CityID int,
  Quantity int,
  IsLimitless bit
);
insert into Stock values (1, 1, 25, false);
insert into Stock values (1, 2, 11, false);
insert into Stock values (2, 1, 84, false);
insert into Stock values (3, 1, 33, false);
insert into Stock values (4, 1, 5, true);
insert into Stock values (4, 3, 1, true);

create table BundleItem (
  BundleID int,
  ItemID int,
  ItemAmount int,
  PriceModifier DECIMAL(12,4)
);
insert into BundleItem values (1, 1, 2, 1.25);
insert into BundleItem values (1, 2, 1, 1);
insert into BundleItem values (1, 3, 1, 1);
insert into BundleItem values (1, 4, 5, 0.75);

create table BundleCategory (
  BundleID int,
  CategoryID int
);
insert into BundleCategory values (1, 4); -- Sweets
insert into BundleCategory values (1, 2); -- Toys
insert into BundleCategory values (1, 8); -- Flowers

以上是关于需要Tricky sql查询,查找子查询的总和的主要内容,如果未能解决你的问题,请参考以下文章

Sql 查询以查找行中的特定总和

行项目表的总和 SQL 子查询

SQL 查询中分组 COUNT 的总和

在没有 FROM 子查询的 JOIN 中写入具有总和限制的 SQL 计数

用于查找重叠客户的 SQL 子查询

SQLAlchemy 子查询 - 总和的平均值