需要棘手的SQL查询,查找子查询的总和

时间:2019-04-19 15:31:28

标签: mysql 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
        ) 

所以我想将我的捆绑包也当作物品展示,并具有相同的字段等。

我的尝试:

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,鲜花)

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

4 个答案:

答案 0 :(得分:2)

您似乎遇到了一些语法问题。您的代码进行了一些更改。详情请参阅查询中的评论。

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
              );

答案 1 :(得分:1)

类似的事情应该起作用

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

答案 2 :(得分:1)

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

这将失败:

SELECT SUM(SELECT 1);

这将起作用:

SELECT SUM((SELECT 1));

答案 3 :(得分:1)

假设1:一个城市中的所有物品都必须有足够的库存,以便该城市有可用的捆绑包。 (请参阅查询注释,了解如何删除此业务规则)

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

假设2:允许库存。数量= 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