当数据位于 GB/TB 时,我的查询是否会成为性能瓶颈
Will my query be bottleneck for performance when data will be in GB/TB
您好,在我们的应用程序中,我们必须在一个长查询中为查询数据库的分析页面上的所有详细信息提供分析。
This is my query here i have removed some fields as content was more than description limit. In my query it is full of subquery. There will
be morethan 20-30 subqueries in select statement. Is this right to
create query like this. Or i use some alternative of it. And yes data
is going to be increase day by day.
Is this right to have subqueries in select statement like this [in this amount] ?
我的查询 [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
在这个查询中,我检索了一个活动中所有卡片的数据。
- 活动将有 20-30 张卡片。 [卡片table]
- 每张卡将分发给用户[没有限制。它将在活动到期日结束。] [saved_card table 将与用户相关 table]
- 卡片可能有兑换码..所以也可以是1到N。可以有 500-1000 ,或任意数量的 redeem_coupons 附在卡上。 [reddem_code table ,与 saved_card 相关 table 将与用户 table ]
相关
- 我正在从其他 table 检索数据,这些数据将 save_card_id 作为外键或 card_id 和 user_id 作为外键。
假设这将 return 每次执行大约 20-30 行,并且大部分时间将花在子查询上,我预测您的响应时间会不一致且令人失望因为 这种复杂的查询对于大多数数据库引擎来说很难建立一个好的执行计划。一个简单但有效的解决方案是将各个子查询转换为函数。这些数据库引擎将能够很好地优化,并且您还将拥有一个更易于长期管理的解决方案。
这里有很多不必要的开支
考虑
(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,这样它就不会被多次评估
您好,在我们的应用程序中,我们必须在一个长查询中为查询数据库的分析页面上的所有详细信息提供分析。
This is my query here i have removed some fields as content was more than description limit. In my query it is full of subquery. There will be morethan 20-30 subqueries in select statement. Is this right to create query like this. Or i use some alternative of it. And yes data is going to be increase day by day.
Is this right to have subqueries in select statement like this [in this amount] ?
我的查询 [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
在这个查询中,我检索了一个活动中所有卡片的数据。
- 活动将有 20-30 张卡片。 [卡片table]
- 每张卡将分发给用户[没有限制。它将在活动到期日结束。] [saved_card table 将与用户相关 table]
- 卡片可能有兑换码..所以也可以是1到N。可以有 500-1000 ,或任意数量的 redeem_coupons 附在卡上。 [reddem_code table ,与 saved_card 相关 table 将与用户 table ] 相关
- 我正在从其他 table 检索数据,这些数据将 save_card_id 作为外键或 card_id 和 user_id 作为外键。
假设这将 return 每次执行大约 20-30 行,并且大部分时间将花在子查询上,我预测您的响应时间会不一致且令人失望因为 这种复杂的查询对于大多数数据库引擎来说很难建立一个好的执行计划。一个简单但有效的解决方案是将各个子查询转换为函数。这些数据库引擎将能够很好地优化,并且您还将拥有一个更易于长期管理的解决方案。
这里有很多不必要的开支
考虑
(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,这样它就不会被多次评估