我有两个表,我用UNION ALL查询 - 一个用于Android,一个用于iPhone。每个表都有自己的设备字段(“android”或“iphone”)。
我每次使用GROUP_CONCAT(DISTINCT `device` ORDER BY `device` SEPARATOR ', ') AS `device`
几次,每次我按其他列分组时(例如date,user_id等)。我也使用相同的GROUP_CONCAT来计算总数。
问题是,当我按日期分组时,我选择设备的GROUP_CONCAT(而不是直接设备),因为有些日期有Android和iPhone购买。 select还包括WHERE或HAVING让用户按特定日期过滤,加入日期的用户数等。当我计算总数时,我在设备上有GROUP_CONCAT,它本身就是GROUP_CONCAT函数。结果可能是“android,android,iphone,iphone”,因为只有Android的日期,只有iPhone的日期和两者的日期(其他查询只能有一个或一些这些选项)。我正在寻找一种方法将此结果转换为“android,iphone”。
目前我正在使用PHP函数:
private function get_device_human_string($fp_device_computer_string)
{
$devices= array(
'android' => 'Android',
'iphone' => 'iPhone'
);
$device_computer_string= strtolower($fp_device_computer_string);
$ret= array();
foreach ($devices as $device_key => $device_human_string)
{
if (strpos($device_computer_string, $device_key) !== false)
{
$ret[]= $device_human_string;
}
}
return implode(', ', $ret);
}
但是我正在寻找一种方法在MySQL中执行它(返回的结果也应该在“Android”中有一个大写字母A和在“iPhone”中有一个大写字母P,但是我不介意使用PHP函数为此)。
顺便说一下,总的SELECT查询是SELECT .... FROM(SELECT .... FROM(.... UNION ALL ....)GROUP BY ....)和GROUP BY是内。如果我没有在内部查询中包含设备,那么外部查询中将没有设备到GROUP_CONCAT。所以我不能直接在设备上使用GROUP_CONCAT。
编辑:这是我正在使用的查询示例(WHERE和HAVING可以根据用户的过滤器进行更改):
SELECT
COUNT(1) AS `count`,
SUM(`joined`) AS `joined`,
SUM(`users`) AS `users`,
SUM(`purchases`) AS `purchases`,
SUM(`credits_purchased`) AS `credits_purchased`,
GROUP_CONCAT(DISTINCT `device` ORDER BY `device` SEPARATOR ', ') AS `device`,
GROUP_CONCAT(DISTINCT `application` ORDER BY `application` SEPARATOR ', ') AS `application`
FROM (
SELECT
`all_purchases`.*,
IF(`users_joined`.`joined` IS NOT NULL, `users_joined`.`joined`, 0) AS `joined`,
'esalne' AS `application`
FROM (
SELECT
DATE(`date`) AS `date`,
COUNT(DISTINCT `user_id`) AS `users`,
COUNT(1) AS `purchases`,
SUM(
IF(
STRCMP(SUBSTRING(`item`, 1, CHAR_LENGTH('esalne.sip.')), 'esalne.sip.')=0,
CAST(SUBSTRING(`item`, CHAR_LENGTH('esalne.sip.')+1) AS UNSIGNED INTEGER),
0
)
) AS `credits_purchased`,
GROUP_CONCAT(DISTINCT `device` ORDER BY `device` SEPARATOR ', ') AS `device`
FROM (
(
SELECT
`id`,
`item`,
`date`,
`status`,
`user` AS `user_id`,
NULL AS `transaction_id`,
'android' AS `device`
FROM `enswitch_android_purchases`
WHERE (`status`=1)
AND (`user` IS NOT NULL)
)
UNION ALL
(
SELECT
`id`,
`item`,
`date`,
`status`,
`user` AS `user_id`,
`transaction_id`,
'iphone' AS `device`
FROM `enswitch_iphone_purchases`
WHERE (`status`=1)
AND (`user` IS NOT NULL)
)
) AS `all_purchases`
GROUP BY DATE(`date`)
) AS `all_purchases`
LEFT JOIN (
SELECT
`join_date` AS `date`,
COUNT(1) AS `joined`
FROM (
SELECT
`user_id`,
MIN(DATE(`date`)) AS `join_date`
FROM (
(
SELECT
`id`,
`item`,
`date`,
`status`,
`user` AS `user_id`,
NULL AS `transaction_id`,
'android' AS `device`
FROM `enswitch_android_purchases`
WHERE (`status`=1)
AND (`user` IS NOT NULL)
)
UNION ALL
(
SELECT
`id`,
`item`,
`date`,
`status`,
`user` AS `user_id`,
`transaction_id`,
'iphone' AS `device`
FROM `enswitch_iphone_purchases`
WHERE (`status`=1)
AND (`user` IS NOT NULL)
)
) AS `all_purchases`
GROUP BY `user_id`
) AS `users`
GROUP BY `date`
) AS `users_joined` ON (`all_purchases`.`date`=`users_joined`.`date`)
HAVING (`date` >= DATE_ADD('2012-11-01', INTERVAL 0 DAY))
AND (`date` < DATE_ADD('2012-11-30', INTERVAL 1 DAY))
AND (`joined` >= 2)
AND (`purchases` <= 30)
AND (`credits_purchased` <= 3000)
) AS `all_purchases_by_dates`
谢谢, URI。
答案 0 :(得分:0)
只是一个草案来说明一个想法:
select d1.device, d2.device, ...
from (
select 'android' as device
union
select 'iphone' as device
) as devices
left outer join mydata d1 on d1.device = devices.device and devices.device = 'android'
left outer join mydata d2 on d2.device = devices.device and devices.device = 'iphone'
inner join ...
where ...
使用'dummy'表和外连接,您可以获取android
和iphone
的所有记录,以便两个设备都是非null或至少其中一个非null。
如果您愿意,可以将d1.device
和d2.device
连接起来,或者以任何其他合适的方式对其group by
进行评估。