MYSQL UNION GROUP BY - mysql

I'm doing this select statement:
SELECT * FROM (
SELECT COUNT(t.text) as count, COUNT(DISTINCT(t.from_user_id)) as usercount, DATE_FORMAT(t.created_at,'%Y-%m-%d %H:00') datepart
FROM TABLE1 t WHERE t.created_at >= '2015-08-12 00:00:00' AND t.created_at <= '2015-08-13 18:30:00' AND t.eliminar IS NULL
GROUP BY datepart) as t
UNION ALL
SELECT * FROM (
SELECT COUNT(b.id) as count, COUNT(DISTINCT(b.from_user_id)) as usercount, DATE_FORMAT(b.created_at,'%Y-%m-%d %H:00') datepart
FROM TABLE2 b WHERE b.created_at >= '2015-08-12 00:00:00' AND b.created_at <= '2015-08-13 18:30:00' AND b.eliminar IS NULL
GROUP BY datepart) as x GROUP BY datepart
this select gets this:
I'm trying to view with datepart grouped but I can't, any idea what I'm doing wrong?
TABLE2 only have (id,from_user_id,eliminar) and all are NULL except created_at, in this row I have entire 2015 year by day and hour, same format as TABLE1

SOLVED:
SELECT DISTINCT * FROM (
SELECT COUNT(t.text) as count, COUNT(DISTINCT(t.from_user_id)) as usercount, DATE_FORMAT(t.created_at,'%Y-%m-%d %H:00') datepart
FROM TABLE1 t WHERE t.created_at >= '2015-08-12 00:00:00' AND t.created_at <= '2015-08-13 18:30:00' AND t.eliminar IS NULL
GROUP BY datepart
UNION ALL
SELECT COUNT(t.id) as count, COUNT(DISTINCT(t.from_user_id)) as usercount, DATE_FORMAT(t.created_at,'%Y-%m-%d %H:00') datepart
FROM TABLE2 t WHERE t.created_at >= '2015-08-12 00:00:00' AND t.created_at <= '2015-08-13 18:30:00' AND t.eliminar IS NULL
GROUP BY datepart) as x GROUP BY datepart ORDER BY datepart

Related

How do I find total sales in my table on SQL?

Attempting to count total number of sales per month what table shows what day EACH sale happened.
My code is as follows:
WITH sales_months AS (
SELECT
'2018-01-01' AS first_day,
'2018-01-31' AS last_day
UNION
SELECT
'2018-02-01' AS first_day,
'2018-02-28' AS last_day
UNION
SELECT
'2018-03-01' AS first_day,
'2018-03-31' AS last_day
UNION
SELECT
'2018-04-01' AS first_day,
'2018-04-31' AS last_day
UNION
SELECT
'2018-05-01' AS first_day,
'2018-05-31' AS last_day
UNION
SELECT
'2018-06-01' AS first_day,
'2018-06-31' AS last_day
UNION
SELECT
'2018-07-01' AS first_day,
'2018-07-31' AS last_day
UNION
SELECT
'2018-08-01' AS first_day,
'2018-08-31' AS last_day
UNION
SELECT
'2018-09-01' AS first_day,
'2018-09-31' AS last_day
UNION
SELECT
'2018-10-01' AS first_day,
'2018-10-31' AS last_day
UNION
SELECT
'2018-11-01' AS first_day,
'2018-11-31' AS last_day
UNION
SELECT
'2018-12-01' AS first_day,
'2018-12-31' AS last_day
)
cross_join AS (
SELECT *
FROM sales_2018
CROSS JOIN sales_months
),
purchase AS (
SELECT GlobalCustomerID, first_day AS sales_month,
CASE
WHEN (SoldDate BETWEEN first_day AND last_day)
THEN 1
ELSE 0
END AS purchased
FROM cross_join
),
purchase_total AS (
SELECT
month,
sum(purchased)
FROM purchase
GROUP BY month;
It returns an error
Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'cross_join AS ( SELECT * FROM sales_2018 CROSS JOIN sales_months ), purchase AS ' at line 50
I believe it may be a problem with how I'm formatting my dates?
Any help is appreciated.
Could you share more of what your table structure looks like? If you want the sum of sales by month, you really shouldn't need to identify the first/last of each month (especially not manually). Something like this would be more straight forward, but I'm not sure of your schema so it may require tweaking.
SELECT
YEAR(SoldDate)
, MONTH(SoldDate)
, COUNT(GlobalCustomerID)
FROM sales_2018
GROUP BY YEAR(SoldDate), MONTH(SoldDate)

Translate mySQL query to Postgres

I'm not able to write a Postgres query. I always get an error or get wrong results. I try to compare counts between today and yesterday.
This MySQL query which is working fine:
SELECT
DATE_FORMAT(crh.date, '%d-%m-%Y') AS name,
DATE_FORMAT(crh.date, '%Y-%m-%d') AS nameGroup,
COUNT(crh.id) AS turnover,
crh_.name AS nameChr,
crh_.nameGroup AS nameGroupChr,
crh_.turnover AS turnoverChr
FROM
camera_reports_history AS crh
LEFT JOIN(
SELECT DATE_FORMAT(crh_.date, '%d-%m-%Y') AS name,
DATE_FORMAT(crh_.date, '%Y-%m-%d') AS nameGroup,
COUNT(crh_.id) AS turnover
FROM
camera_reports_history AS crh_
WHERE
crh_.date >= '2018-07-09 00:00:00' AND crh_.date <= '2018-07-20 14:02:22'
GROUP BY
nameGroup
) AS crh_
ON
crh_.nameGroup = DATE_FORMAT(SUBDATE(crh.date, 1),
'%Y-%m-%d')
WHERE
crh.date >= '2018-07-10 00:00:00' AND crh.date <= '2018-07-20 14:02:22'
GROUP BY
nameGroup
Result:
"10-07-2018","2018-07-10","418","09-07-2018","2018-07-09","581"
"11-07-2018","2018-07-11","389","10-07-2018","2018-07-10","418"
"12-07-2018","2018-07-12","453","11-07-2018","2018-07-11","389"
"13-07-2018","2018-07-13","401","12-07-2018","2018-07-12","453"
...
My PostgreSQL query looks like this:
SELECT
to_char(crh."date", 'DD-MM-YYYY') AS name,
to_char(crh."date", 'YYYY-MM-DD') AS nameGroup,
COUNT(crh.id) AS turnover,
crh_.name AS nameChr,
crh_.nameGroup AS nameGroupChr,
crh_.turnover AS turnoverChr
FROM
camera_reports_history AS crh
LEFT JOIN(
SELECT to_char(crh_."date", 'DD-MM-YYYY') AS name,
to_char(crh_."date", 'YYYY-MM-DD') AS nameGroup,
COUNT(crh_.id) AS turnover
FROM
camera_reports_history AS crh_
WHERE
crh_.date >= '2018-07-09 00:00:00' AND crh_.date <= '2018-07-20 14:02:22'
GROUP BY
nameGroup,
name
ORDER BY
nameGroup
) AS crh_
ON
crh_.nameGroup = to_char(
crh."date" - INTERVAL '1 day',
'YYYY-MM-DD'
)
WHERE
crh.date >= '2018-07-10 00:00:00' AND crh.date <= '2018-07-20 14:02:22'
GROUP BY
nameGroup,
name
ORDER BY
nameGroup
errors:
ERROR: column `crh.date` must appear in the GROUP BY clause or be used in an aggregate function
if I insert necessary columns:
GROUP BY nameGroup, name, date, crh_.nameGroup, crh_.name, crh_.turnover
I will get useless results.
Could someone help me please?
I found a solution:
SELECT
DISTINCT ON(nameGroup)
to_char(crh."date", 'DD-MM-YYYY') AS name,
to_char(crh."date", 'YYYY-MM-DD') AS nameGroup,
crh__.turnover AS turnover,
crh_.name AS nameChr,
crh_.nameGroup AS nameGroupChr,
crh_.turnover AS turnoverChr
FROM
camera_reports_history AS crh
LEFT JOIN(
SELECT
to_char(crh__."date", 'YYYY-MM-DD') AS nameGroup__,
COUNT(crh__.id) AS turnover
FROM
camera_reports_history AS crh__
WHERE
crh__.date >= '2018-07-10 00:00:00' AND crh__.date <= '2018-07-20 14:02:22'
GROUP BY
nameGroup__
) AS crh__ ON crh__.nameGroup__ = to_char((crh."date"), 'YYYY-MM-DD')
LEFT JOIN(
SELECT to_char(crh_."date", 'DD-MM-YYYY') AS name,
to_char(crh_."date", 'YYYY-MM-DD') AS nameGroup,
COUNT(crh_.id) AS turnover
FROM
camera_reports_history AS crh_
WHERE
crh_.date >= '2018-07-09 00:00:00' AND crh_.date <= '2018-07-20 14:02:22'
GROUP BY
nameGroup,
name
ORDER BY
nameGroup
) AS crh_ ON crh_.nameGroup = to_char((crh."date" - INTERVAL '1 day'), 'YYYY-MM-DD')
WHERE
crh.date >= '2018-07-10 00:00:00' AND crh.date <= '2018-07-20 14:02:22'
GROUP BY
nameGroup,
name,
crh.date,
crh__.turnover,
crh_.nameGroup,
crh_.name,
crh_.turnover
ORDER BY
nameGroup
I make a 2nd LEFT JOIN to count the results and use DISTINCT ON(nameGroup) on the main SELECT.
I think it's not a perfect query. but my problem is solved at this moment.
Please feel free to optimate this query.
Transaction blocks work well in postgresql, so instead of a complex compound statement that attempts to sort, join, group and filter all at once, you can use temporary tables. This allows you to break the steps up into multiple simple statements and store intermediate data in temp tables that disappear at the end of the transaction block.
I think you'll find this method a lot easier to debug.

MySQL UNION - Replicating a Sub Query

This is my current query:
Select Month as ReqMonth1,
sum(TotalUsage) As ReqCount1,
sum(Memberbase) as Club_updates_Records1,
round(sum(TotalUsage)/sum(Memberbase)*100,0) AS UsagePerc
from(
Select * from (
SELECT
CAST(DATE_FORMAT(Log_Date, '%b-%y') AS CHAR(100)) AS 'Month',
CAST(DATE_FORMAT(Log_Date, '%y-%m') AS CHAR(100)) AS 'Monthsort',
count(Requests.`fk_Members_ID`) AS TotalUsage,
0 as Memberbase
FROM
`Requests` Requests INNER JOIN `Members` Members ON Requests.`fk_Members_ID` = Members.`ID`
WHERE
cast(Requests.`Log_date` as date) BETWEEN date_sub(if($P{StartDate}>'2016-06-01',$P{StartDate},'2016-05-01'), Interval 4 month) and $P{EndDate} AND $P{EndDate}
AND Members.`Club` = $P{Club}
GROUP BY
CAST(DATE_FORMAT(Log_Date, '%M-%y') AS CHAR(100)) ) as A
UNION ALL
Select * from (
SELECT
CAST(DATE_FORMAT(Club_updates.`Update_Date`, '%b-%y') AS CHAR(100)) AS 'Month',
CAST(DATE_FORMAT(Club_updates.`Update_Date`, '%y-%m') AS CHAR(100)) AS 'Monthsort',
0 AS TotalUsage,
ifnull(max(Club_updates.`Records`),1) AS MemberBase
FROM
`Club updates` Club_updates
WHERE
cast(Club_updates.`Update_Date` as date) BETWEEN date_sub(if($P{StartDate}>'2016-06-01',$P{StartDate},'2016-05-01'), Interval 4 month) and $P{EndDate} AND $P{EndDate}
AND Club_updates.`fk_Club` = $P{Club}
GROUP BY CAST(DATE_FORMAT(Club_updates.`Update_Date`, '%M-%y') AS CHAR(100)) ) As B) as D
group by Month
Order by MonthSort
I'm trying to replicate/add another sub query "A" with the change on the Close_Date field instead of the Log_Date field in the WHERE clause.
Basically resulting a sum of both subqueries only in the "ReqCount1" field.
Any help would be appreciated.
Ok, got it solved
here's the solution(with an additional condition in the WHERE clause)
Select Month as ReqMonth1,
sum(TotalUsage) As ReqCount1,
sum(Memberbase) as Club_updates_Records1,
round(sum(TotalUsage)/sum(Memberbase)*100,0) AS UsagePerc
from(
Select * from (
SELECT
CAST(DATE_FORMAT(Log_Date, '%b-%y') AS CHAR(100)) AS 'Month',
CAST(DATE_FORMAT(Log_Date, '%y-%m') AS CHAR(100)) AS 'Monthsort',
count(Requests.`fk_Members_ID`) AS TotalUsage,
0 as Memberbase
FROM
`Requests` Requests INNER JOIN `Members` Members ON Requests.`fk_Members_ID` = Members.`ID`
WHERE
cast(Requests.`Log_date` as date) BETWEEN date_sub(if($P{StartDate}>'2016-06-01',$P{StartDate},'2016-05-01'), Interval 4 month) and $P{EndDate} AND $P{EndDate}
AND Members.`Club` = $P{Club} AND Requests.`Request_Type` <> 7
GROUP BY
CAST(DATE_FORMAT(Log_Date, '%M-%y') AS CHAR(100)) ) as A
UNION ALL
Select * from (
SELECT
CAST(DATE_FORMAT(Close_Date, '%b-%y') AS CHAR(100)) AS 'Month',
CAST(DATE_FORMAT(Close_Date, '%y-%m') AS CHAR(100)) AS 'Monthsort',
count(Requests.`fk_Members_ID`) AS TotalUsage,
0 as Memberbase
FROM
`Requests` Requests INNER JOIN `Members` Members ON Requests.`fk_Members_ID` = Members.`ID`
WHERE
cast(Requests.`Close_Date` as date) BETWEEN date_sub(if($P{StartDate}>'2016-06-01',$P{StartDate},'2016-05-01'), Interval 4 month) and $P{EndDate} AND $P{EndDate}
AND Members.`Club` = $P{Club} AND Requests.`Request_Type` = 7
GROUP BY
CAST(DATE_FORMAT(Close_Date, '%M-%y') AS CHAR(100)) ) as G
UNION ALL
Select * from (
SELECT
CAST(DATE_FORMAT(Club_updates.`Update_Date`, '%b-%y') AS CHAR(100)) AS 'Month',
CAST(DATE_FORMAT(Club_updates.`Update_Date`, '%y-%m') AS CHAR(100)) AS 'Monthsort',
0 AS TotalUsage,
ifnull(max(Club_updates.`Records`),1) AS MemberBase
FROM
`Club updates` Club_updates
WHERE
cast(Club_updates.`Update_Date` as date) BETWEEN date_sub(if($P{StartDate}>'2016-06-01',$P{StartDate},'2016-05-01'), Interval 4 month) and $P{EndDate} AND $P{EndDate}
AND Club_updates.`fk_Club` = $P{Club}
GROUP BY CAST(DATE_FORMAT(Club_updates.`Update_Date`, '%M-%y') AS CHAR(100)) ) As B) as D
group by Month
Order by MonthSort

MySQL return 0 if query is null

This query should select some statistic values form a table:
(SELECT MAX(`id`) as `count` FROM `stats` LIMIT 1)
UNION (SELECT COUNT(*) as `count` FROM `stats` WHERE DATE(`time`) >= (NOW() - INTERVAL 1 DAY) LIMIT 1)
UNION (SELECT COUNT(*) as `count` FROM `stats` WHERE DATE(`time`) >= (NOW() - INTERVAL 7 DAY) LIMIT 1)
UNION (SELECT COUNT(*) as `count` FROM `stats` WHERE DATE(`time`) >= (NOW() - INTERVAL 30 DAY) LIMIT 1)
UNION (SELECT DATE_FORMAT(MIN(`time`), '%D of %M, %Y') as `count` FROM `stats` LIMIT 1)
I tried this, but it doesn't work
(SELECT MAX(`id`) as `count` FROM `stats` LIMIT 1)
UNION IFNULL((SELECT COUNT(*) as `count` FROM `stats` WHERE DATE(`time`) >= (NOW() - INTERVAL 1 DAY) LIMIT 1), '0')
UNION IFNULL((SELECT COUNT(*) as `count` FROM `stats` WHERE DATE(`time`) >= (NOW() - INTERVAL 7 DAY) LIMIT 1), '0')
UNION IFNULL((SELECT COUNT(*) as `count` FROM `stats` WHERE DATE(`time`) >= (NOW() - INTERVAL 30 DAY) LIMIT 1), '0')
UNION IFNULL((SELECT DATE_FORMAT(MIN(`time`), '%D of %M, %Y') as `count` FROM `stats` LIMIT 1), '0')
You have to do SELECT on IFNULL:
SELECT MAX(`id`) as `count` FROM `stats` LIMIT 1
UNION
SELECT IFNULL((SELECT COUNT(*) as `count`
FROM `stats`
WHERE DATE(`time`) >= (NOW() - INTERVAL 1 DAY) LIMIT 1), 0)
UNION
SELECT IFNULL((SELECT COUNT(*) as `count`
FROM `stats`
WHERE DATE(`time`) >= (NOW() - INTERVAL 7 DAY) LIMIT 1), 0)
UNION
SELECT IFNULL((SELECT COUNT(*) as `count`
FROM `stats`
WHERE DATE(`time`) >= (NOW() - INTERVAL 30 DAY) LIMIT 1), 0)
UNION
SELECT IFNULL((SELECT DATE_FORMAT(MIN(`time`), '%D of %M, %Y') as `count`
FROM `stats` LIMIT 1), 0)
You also have to use 0 instead of '0' and get rid of the parentheses surrounding the first query.

MySQL COUNT(*) GROUP BY HAVING COUNT=?

This my Query
SELECT COUNT(*) as total, toys, date FROM T1
WHERE (date >= '2012-06-26'AND date < '2012-06-30') AND (Avail > '0')
UNION
SELECT COUNT(*) as total, toys, date FROM T2
WHERE (date >= '2012-06-26'AND date < '2012-06-30') AND (Avail > '0')
UNION
SELECT COUNT(*) as total, toys, date FROM T3
WHERE (date >= '2012-06-26'AND date < '2012-06-30') AND (Avail > '0')
GROUP BY RoomType
HAVING COUNT( total ) = 4
Output result
count Toys date
3 Bibi 2012-06-26
4 Baba 2012-06-26
How can i get MYSQL to show results only for count=4
SELECT * FROM (
SELECT COUNT(*) as total, toys, date FROM T1
WHERE (date >= '2012-06-26' AND date < '2012-06-30') AND (Avail > '0')
GROUP BY RoomType
UNION
SELECT COUNT(*) as total, toys, date FROM T2
WHERE (date >= '2012-06-26' AND date < '2012-06-30') AND (Avail > '0')
GROUP BY RoomType
UNION
SELECT COUNT(*) as total, toys, date FROM T3
WHERE (date >= '2012-06-26'AND date < '2012-06-30') AND (Avail > '0')
GROUP BY RoomType) AS src
WHERE total = 4;
Please, note, that for proper data groupping you must have all columns either in the GROUP BY clause or as arguments to the aggregate functions. It is MySQL feature to allow you to avoid this restriction, but it might lead you to the unexpected results.
You need group by first then union the result.
SELECT COUNT(*) as total, toys, date FROM T1
WHERE (date >= '2012-06-26'AND date < '2012-06-30') AND (Avail > '0')
GROUP BY RoomType HAVING COUNT( *) = 4
UNION
SELECT COUNT(*) as total, toys, date FROM T2
WHERE (date >= '2012-06-26'AND date < '2012-06-30') AND (Avail > '0')
GROUP BY RoomType HAVING COUNT( * ) = 4
UNION
SELECT COUNT(*) as total, toys, date FROM T3
WHERE (date >= '2012-06-26'AND date < '2012-06-30') AND (Avail > '0')
GROUP BY RoomType HAVING COUNT( * ) = 4