您好,在我们的应用中,我们必须在一个长查询中为分析页面i查询数据库的所有详细信息提供分析。
这是我的查询,我删除了一些字段,因为内容超出了描述限制。在我的查询中,它充满了子查询。这里将 在select语句中超过20-30个子查询。这是对的 像这样创建查询。或者我使用它的一些替代品。是的数据 将会日益增加。
这样的选择语句中的子查询是否正确[以此数量]?
我的查询[更新于2015年8月13日]
SELECT COUNT(users.user_id),
cards.card_id,
GROUP_CONCAT(users.user_id),
GROUP_CONCAT(redeem_code.redeem_id),
CASE
WHEN cards.what_to_broadcast = "0"
THEN
"Information Card"
WHEN cards.what_to_broadcast = "1"
THEN
"Rating Card"
WHEN cards.what_to_broadcast = "2"
THEN
CASE
WHEN cards.discount_type = "2"
THEN
"Price Cut Discount Card"
WHEN cards.discount_type = "1"
THEN
"Buy X Get Y Discount Card"
WHEN cards.discount_type = "0"
THEN
"Fixed Discount Card"
ELSE
"Fixed Discount Card"
END
WHEN cards.what_to_broadcast = "4"
THEN
CASE
WHEN cards.question_type = "1"
THEN
"Multiple Choice Question Card"
WHEN cards.question_type = "2"
THEN
"Single Choice Question Card"
WHEN cards.question_type = "3"
THEN
"Discriptive Question Card"
ELSE
"Multiple Choice Question Card"
END
ELSE
"Information Card x"
END
AS cardType,
cards.name AS cardTitle,
cards.what_to_broadcast,
cards.card_id,
COUNT(saved_card.saved_card_id) AS cardReach,
COUNT(DISTINCT saved_card.redeem_id) AS cardReachCoupons,
SUM((CASE WHEN saved_card.status = "1" THEN 1 ELSE 0 END))
AS sumOfSavedCard,
SUM((CASE WHEN users.gender = "1" THEN 1 ELSE 0 END)) AS maleRecipient,
SUM((CASE WHEN users.gender = "2" THEN 1 ELSE 0 END))
AS femaleRecipient,
SUM(
(CASE
WHEN saved_card.status = "1"
THEN
CASE WHEN users.gender = "1" THEN 1 ELSE 0 END
ELSE
0
END))
AS sumOfSavedCardMaleRecipient,
SUM(
(CASE
WHEN saved_card.status = "1"
THEN
CASE WHEN users.gender = "2" THEN 1 ELSE 0 END
ELSE
0
END))
AS sumOfSavedCardFemaleRecipient,
IFNULL(
(SELECT COUNT(*)
FROM rating_like
INNER JOIN users ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.is_like = "1"
AND rating_like.card_id = cards.card_id),
0)
AS likers,
IFNULL(
(SELECT COUNT(*)
FROM rating_like
INNER JOIN users ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.is_like = "1"
AND rating_like.card_id = cards.card_id
AND users.gender = "1"),
0)
AS maleLikersMain,
IFNULL(
(SELECT COUNT(*)
FROM rating_like
INNER JOIN users ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.is_like = "1"
AND rating_like.card_id = cards.card_id
AND users.gender = "2"),
0)
AS femaleLikersMain,
IFNULL(
(SELECT COUNT(*)
FROM rating_like
INNER JOIN users ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.see_extra_info = "1"
AND rating_like.card_id = cards.card_id),
0)
AS seenExtraInfo,
IFNULL(
(SELECT COUNT(*)
FROM rating_like
INNER JOIN users ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.see_extra_info = "1"
AND rating_like.card_id = cards.card_id
AND users.gender = "1"),
0)
AS maleSeenExtraInfo,
IFNULL(
(SELECT COUNT(*)
FROM rating_like
INNER JOIN users ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.see_extra_info = "1"
AND rating_like.card_id = cards.card_id
AND users.gender = "2"),
0)
AS femaleSeenExtraInfo,
IFNULL(
(SELECT SUM(card_share.count) AS card_share
FROM card_share
INNER JOIN users ON card_share.user_id = users.user_id
WHERE users.status = "1"
AND card_share.status = "1"
AND card_share.card_id = cards.card_id),
0)
AS card_share_main,
IFNULL(
(SELECT SUM(card_share.count) AS card_share
FROM card_share
INNER JOIN users ON card_share.user_id = users.user_id
WHERE users.status = "1"
AND card_share.status = "1"
AND card_share.card_id = cards.card_id
AND users.gender = "1"),
0)
AS card_share_by_male,
IFNULL(
(SELECT SUM(card_share.count) AS card_share
FROM card_share
INNER JOIN users ON card_share.user_id = users.user_id
WHERE users.status = "1"
AND card_share.status = "1"
AND card_share.card_id = cards.card_id
AND users.gender = "2"),
0)
AS card_share_by_female,
IFNULL(
(SELECT COUNT(rating_like.rating_like_id)
FROM rating_like
INNER JOIN users ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.has_rated = "1"
AND rating_like.rate = "1"
AND rating_like.card_id = cards.card_id),
0)
AS rate1,
IFNULL(
(SELECT COUNT(rating_like.rating_like_id)
FROM rating_like
INNER JOIN users ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.has_rated = "1"
AND rating_like.rate = "1"
AND rating_like.card_id = cards.card_id
AND users.gender = "1"),
0)
AS rate1_by_male,
IFNULL(
(SELECT COUNT(rating_like.rating_like_id)
FROM rating_like
INNER JOIN users ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.has_rated = "1"
AND rating_like.rate = "1"
AND rating_like.card_id = cards.card_id
AND users.gender = "2"),
0)
AS rate1_by_female,
IFNULL(
(SELECT COUNT(rating_like.rating_like_id)
FROM rating_like
INNER JOIN users ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.has_rated = "1"
AND rating_like.rate = "2"
AND rating_like.card_id = cards.card_id),
0)
AS rate2,
IFNULL(
(SELECT COUNT(rating_like.rating_like_id)
FROM rating_like
INNER JOIN users ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.has_rated = "1"
AND rating_like.rate = "2"
AND rating_like.card_id = cards.card_id
AND users.gender = "1"),
0)
AS rate2_by_male,
IFNULL(
(SELECT COUNT(rating_like.rating_like_id)
FROM rating_like
INNER JOIN users ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.has_rated = "1"
AND rating_like.rate = "2"
AND rating_like.card_id = cards.card_id
AND users.gender = "2"),
0)
AS rate2_by_female,
IFNULL(
(SELECT COUNT(rating_like.rating_like_id)
FROM rating_like
INNER JOIN users ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.has_rated = "1"
AND rating_like.rate = "3"
AND rating_like.card_id = cards.card_id),
0)
AS rate3,
IFNULL(
(SELECT COUNT(rating_like.rating_like_id)
FROM rating_like
INNER JOIN users ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.has_rated = "1"
AND rating_like.rate = "3"
AND rating_like.card_id = cards.card_id
AND users.gender = "1"),
0)
AS rate3_by_male,
IFNULL(
(SELECT COUNT(rating_like.rating_like_id)
FROM rating_like
INNER JOIN users ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.has_rated = "1"
AND rating_like.rate = "3"
AND rating_like.card_id = cards.card_id
AND users.gender = "2"),
0)
AS rate3_by_female,
IFNULL(
(SELECT COUNT(rating_like.rating_like_id)
FROM rating_like
INNER JOIN users ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.has_rated = "1"
AND rating_like.rate = "4"
AND rating_like.card_id = cards.card_id),
0)
AS rate4,
IFNULL(
(SELECT COUNT(rating_like.rating_like_id)
FROM rating_like
INNER JOIN users ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.has_rated = "1"
AND rating_like.rate = "4"
AND rating_like.card_id = cards.card_id
AND users.gender = "1"),
0)
AS rate4_by_male,
IFNULL(
(SELECT COUNT(rating_like.rating_like_id)
FROM rating_like
INNER JOIN users ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.has_rated = "1"
AND rating_like.rate = "4"
AND rating_like.card_id = cards.card_id
AND users.gender = "2"),
0)
AS rate4_by_female,
IFNULL(
(SELECT COUNT(rating_like.rating_like_id)
FROM rating_like
INNER JOIN users ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.has_rated = "1"
AND rating_like.rate = "5"
AND rating_like.card_id = cards.card_id),
0)
AS rate5,
IFNULL(
(SELECT COUNT(rating_like.rating_like_id)
FROM rating_like
INNER JOIN users ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.has_rated = "1"
AND rating_like.rate = "5"
AND rating_like.card_id = cards.card_id
AND users.gender = "1"),
0)
AS rate5_by_male,
IFNULL(
(SELECT COUNT(rating_like.rating_like_id)
FROM rating_like
INNER JOIN users ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.has_rated = "1"
AND rating_like.rate = "5"
AND rating_like.card_id = cards.card_id
AND users.gender = "2"),
0)
AS rate5_by_female,
IFNULL(
(SELECT COUNT(redeem_code.redeem_id)
FROM redeem_code
WHERE redeem_code.card_id = cards.card_id
AND redeem_code.status = "1"),
0)
AS totalCoupons,
IFNULL(
(SELECT COUNT(DISTINCT redeem_code.redeem_id)
FROM redeem_code
INNER JOIN saved_card
ON saved_card.redeem_id = redeem_code.redeem_id
WHERE redeem_code.card_id = cards.card_id
AND redeem_code.status = "1"
AND redeem_code.used_coupon = "2"),
0)
AS totalRedeemCoupons,
IFNULL(
(SELECT COUNT(DISTINCT redeem_code.redeem_id)
FROM redeem_code
INNER JOIN saved_card
ON saved_card.redeem_id = redeem_code.redeem_id
INNER JOIN users ON saved_card.user_id = users.user_id
WHERE redeem_code.card_id = cards.card_id
AND redeem_code.status = "1"
AND redeem_code.used_coupon = "2"
AND users.user_id = "1"),
0)
AS maleRedeemCoupons,
IFNULL(
(SELECT COUNT(DISTINCT redeem_code.redeem_id)
FROM redeem_code
INNER JOIN saved_card
ON saved_card.redeem_id = redeem_code.redeem_id
INNER JOIN users ON saved_card.user_id = users.user_id
WHERE redeem_code.card_id = cards.card_id
AND redeem_code.status = "1"
AND redeem_code.used_coupon = "2"
AND users.user_id = "2"),
0)
AS femaleRedeemCoupons,
(SELECT GROUP_CONCAT(options, "/~", cNum)
FROM (SELECT GROUP_CONCAT(
DISTINCT COALESCE(card_question_options.value, ""))
AS options,
SUM(
CASE
WHEN saved_card_feedbacks.card_question_option_id =
card_question_options.card_question_option_id
THEN
1
ELSE
0
END)
AS cNum,
c2.card_id
FROM card_question_options
INNER JOIN cards c2
ON c2.card_id = card_question_options.card_id
INNER JOIN saved_card
ON c2.card_id = saved_card.card_id
AND saved_card.status IN ("1", "2")
LEFT JOIN saved_card_feedbacks
ON saved_card_feedbacks.saved_card_id =
saved_card.saved_card_id
AND saved_card_feedbacks.status = "1"
INNER JOIN users
ON saved_card.user_id = users.user_id
AND users.status = "1"
WHERE 1 AND card_question_options.status = "1"
GROUP BY card_question_options.card_question_option_id)
AS table1
WHERE table1.card_id = cards.card_id)
AS cardOptionsMain,
(SELECT GROUP_CONCAT(options, "/~", cNum)
FROM (SELECT GROUP_CONCAT(
DISTINCT COALESCE(card_question_options.value, ""))
AS options,
SUM(
CASE
WHEN saved_card_feedbacks.card_question_option_id =
card_question_options.card_question_option_id
THEN
1
ELSE
0
END)
AS cNum,
c2.card_id
FROM card_question_options
INNER JOIN cards c2
ON c2.card_id = card_question_options.card_id
INNER JOIN saved_card
ON c2.card_id = saved_card.card_id
AND saved_card.status IN ("1", "2")
LEFT JOIN saved_card_feedbacks
ON saved_card_feedbacks.saved_card_id =
saved_card.saved_card_id
AND saved_card_feedbacks.status = "1"
INNER JOIN users
ON saved_card.user_id = users.user_id
AND users.status = "1"
AND users.gender = "1"
WHERE 1 AND card_question_options.status = "1"
GROUP BY card_question_options.card_question_option_id)
AS table1
WHERE table1.card_id = cards.card_id)
AS cardOptionsMainMale,
(SELECT GROUP_CONCAT(options, "/~", cNum)
FROM (SELECT GROUP_CONCAT(
DISTINCT COALESCE(card_question_options.value, ""))
AS options,
SUM(
CASE
WHEN saved_card_feedbacks.card_question_option_id =
card_question_options.card_question_option_id
THEN
1
ELSE
0
END)
AS cNum,
c2.card_id
FROM card_question_options
INNER JOIN cards c2
ON c2.card_id = card_question_options.card_id
INNER JOIN saved_card
ON c2.card_id = saved_card.card_id
AND saved_card.status IN ("1", "2")
LEFT JOIN saved_card_feedbacks
ON saved_card_feedbacks.saved_card_id =
saved_card.saved_card_id
AND saved_card_feedbacks.status = "1"
INNER JOIN users
ON saved_card.user_id = users.user_id
AND users.status = "1"
AND users.gender = "2"
WHERE 1 AND card_question_options.status = "1"
GROUP BY card_question_options.card_question_option_id)
AS table1
WHERE table1.card_id = cards.card_id)
AS cardOptionsMainFemale
FROM cards
INNER JOIN campaigns ON cards.camapign_id = campaigns.campaign_id
INNER JOIN saved_card ON saved_card.card_id = cards.card_id
INNER JOIN users ON saved_card.user_id = users.user_id
LEFT JOIN redeem_code ON saved_card.redeem_id = redeem_code.redeem_id
WHERE cards.status = "1"
AND users.status = "1"
AND saved_card.status IN ("1", "2")
AND campaigns.campaign_id = :campaign_id
GROUP BY cards.card_id
在此查询中,我会检索一个广告系列中所有卡片的数据。
答案 0 :(得分:1)
假设这将在每次执行时返回大约20-30行,并且大部分时间将花费在子查询中,我预测您将会有不一致且令人失望的响应时间,因为对于大多数数据库引擎而言,这种复杂性的查询很难为其建立良好的执行计划。一个简单但有效的解决方案是将各个子查询转换为函数。这些数据库引擎能够很好地进行优化,并且您还可以获得一个更容易管理的解决方案。
答案 1 :(得分:1)
这里有很多不必要的开支
考虑
(SELECT SUM((CASE WHEN users.gender = "2" THEN 1 ELSE 0 END) AS femaleSeenExtraInfoInner
FROM rating_like
JOIN users
ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.see_extra_info = "1"
AND rating_like.card_id = cards.card_id
GROUP BY rating_like.card_id)
IS NULL
为什么所有的工作都要测试null? 减少工作量的结果相同
(SELECT top 1 users.gender AS femaleSeenExtraInfoInner
FROM rating_like
JOIN users
ON rating_like.user_id = users.user_id
AND users.status = "1"
AND rating_like.status = "1"
AND rating_like.see_extra_info = "1"
AND rating_like.card_id = cards.card_id)
IS NULL
即使您确实需要计数
SELECT SUM((CASE WHEN users.gender = "2" THEN 1 ELSE 0 END) AS femaleSeenExtraInfoInner
FROM rating_like
JOIN users
ON rating_like.user_id = users.user_id
WHERE users.status = "1"
AND rating_like.status = "1"
AND rating_like.see_extra_info = "1"
AND rating_like.card_id = cards.card_id
GROUP BY rating_like.card_id
为什么按rating_like.card_id进行分组?您正在加入一张cards.card_id。
SELECT count(*) AS femaleSeenExtraInfoInner
FROM rating_like
JOIN users
ON rating_like.user_id = users.user_id
AND rating_like.card_id = cards.card_id
AND users.status = "1"
AND rating_like.status = "1"
AND rating_like.see_extra_info = "1"
AND users.gender = "2"
或者只需使用
使其更简单with cte_femaleSeenExtraInfoInner (card_id, count)
as
(
SELECT users.card_id, count(*) AS count
FROM rating_like
JOIN users
ON rating_like.user_id = users.user_id
AND users.status = "1"
AND rating_like.status = "1"
AND rating_like.see_extra_info = "1"
AND users.gender = "2"
group by users.card_id
)
select distinct
cards.user_id, isnull(cte_femaleSeenExtraInfoInner.count, 0)
FROM cards
left join cte_femaleSeenExtraInfoInner
on cte_femaleSeenExtraInfoInner.user_id = cards.user_id
....
你甚至可以用
加倍性别SELECT users.card_id, users.gender, count(*) AS count
FROM rating_like
JOIN users
ON rating_like.user_id = users.user_id
AND users.status = "1"
AND rating_like.status = "1"
AND rating_like.see_extra_info = "1"
AND users.gender = in ("1", "2")
group by users.card_id, users.gender
更好地将cte实现为#temp,因此不会多次评估