0

我有 2 张桌子:itemsitems_purchased. tag名称和其他描述性信息在表items中,每个项目的购买次数保存在items_purchased表中。这些表是JOIN在 item_id 上编辑的。

到目前为止,这是我的查询:

(select *, sum(purchaseyesno) as tots from items join items_purchased on items.item_id=items_purchased.item_id where tag = 'History' and deleted!=1 and pub_priv!=1    order by tots desc limit 1)
UNION ALL
(select *, sum(purchaseyesno) as tots from items join items_purchased on items.item_id=items_purchased.item_id where tag = 'Medicine' and deleted!=1 and pub_priv!=1  order by tots desc limit 1)
UNION ALL
(select *, sum(purchaseyesno) as tots from items join items_purchased on items.item_id=items_purchased.item_id where tag = 'Biology' and deleted!=1 and pub_priv!=1  order by tots desc limit 1)
//... more tags (20 in all) would follow

问题是尚未购买带有某些标签的商品,因此查询会抛出Column "item_id" cannot be null.

这是示例表:

            items              |     items_purchased   |   
  item_id   tag      title     | item_id  purchaseyesno|
    1     Biology  DNA is cool |    1         1        | 
    2     Medicine  Doctors    |    2         1        |  
    3      Law    Laws are cool|    4         1        |    
    4     Biology DNA NOT cool |    1         1        |

样本结果:

item_id   tag       title      tots
  1      Biology   DNA is cool  2
  2      Medicine  Doctors      1
  3       Law   Laws are cool   0

2个问题:

  1. 如果结果是这样,我该如何排除这些SELECT语句之一NULL
  2. 有没有更好的方法来执行此查询,而不是 20 条选择语句由 19UNION ALL秒连接?
4

2 回答 2

2

你只是想对你的结果进行分组——没有比这更复杂的了(UNION看不到!):

SELECT   items.*, SUM(purchaseyesno) AS tots
FROM     items JOIN items_purchased USING (item_id)
GROUP BY item_id

更新

在下面的评论和对 OP 问题的更新之后,很明显这个问题比最初想象的要复杂得多:事实上,它是分组最大问题的一个特例。

但是,必须取最大值的列本身就是另一个分组聚合的结果( 的总和purchaseyesno)。

因此,一个人的查询对于子查询变得相当不优雅:

SELECT *
FROM (
  SELECT   items.*, IFNULL(SUM(purchaseyesno),0) AS tots
  FROM     items LEFT JOIN items_purchased ON folder_id = item_id
  GROUP BY item_id
) AS t NATURAL JOIN (
  SELECT tag, MAX(tots) AS tots
  FROM (
    SELECT   items.*, IFNULL(SUM(purchaseyesno),0) AS tots
    FROM     items LEFT JOIN items_purchased ON folder_id = item_id
    GROUP BY item_id
  ) AS u
  GROUP BY tag
) AS v
GROUP BY tag

sqlfiddle上查看。

这里发生的情况是(使用外连接来包含表Law中没有引用的记录items_purchased),我们获取每个项目(物化表u)的购买总和,然后确定相同项目的最大购买数量标签名称。

然后,我们将结果(物化表)与标签名称和购买次数的v第一个表(u再次物化为表)连接起来。t

最后,我们再次对结果进行分组,tag以确保如果具有相同标签的多个项目具有相同的最大购买次数,则仅不确定返回其中一个。

于 2012-06-26T10:54:00.060 回答
0

创建一个主表 tags ,并将其 id 存储在用作名称的表中。那么下面的查询将是您问题的解决方案..

select *, sum(purchaseyesno) as tots 
from items left join 
items_purchased ip on (items.item_id=items_purchased.item_id)
inner join tag_table on (tag_table.id=tagId)
where  deleted!=1 and pub_priv!=1 and not items.item_id is null group by tagID
于 2012-06-26T10:44:41.073 回答