Select multiples counts - mysql

My select:
SELECT DISTINCT
(SELECT COUNT(*)
FROM t_table
WHERE year(date) BETWEEN '2013' AND '2013' AND month(date) BETWEEN '1' AND '12' AND date!=cad_em) as total1,
(SELECT COUNT(*)
FROM t_table
WHERE year(date) BETWEEN '2013' AND '2013' AND month(date) BETWEEN '1' AND '12' AND date=cad_em ) as total2
FROM t_table
GROUP BY date
Return:
total1 | total2
1 4
But I would like to return the date
Exemple:
date | total1 | total2
2013-10 7 8
2013-11 1 4
2013-12 2 5
How could I do to show the same response to my example?
Thanks!!

You can use conditional sum to simplify things. Also, I'm not sure your where condition makes a lot of sense, unless these are parameters -
select
date,
sum( if(date = cad_em, 0, 1) ) as total1,
sum( if(date = cad_em, 1, 0) ) as total2
from
t_table
where year(date) = 2013 and month(date) between 1 and 12
group by date

I think you want something like this:
select max(`date`) as `date`, sum(`date` <> cad_em) as total1, sum(`date` = cad_em) as total2
from t_table
where year(`date`) = 2013;
You see to want the maximum of the date, but that is just a guess.

Related

Calculate Ratio of two different SQL queries result that return numbers

I have Query 1
SELECT COUNT(DISTINCT user_id) total_daily_active_user_group_month FROM (SELECT user_id , MONTHNAME(time) mon , COUNT(*) cnt FROM ACTIVITIES
WHERE MONTH(time) = MONTH(NOW() - INTERVAL 1 MONTH) GROUP by user_id, MONTH(time) ) as x
Returns 18
Query 2
SELECT COUNT(DISTINCT user_id) total_daily_active_user_group_month FROM (SELECT user_id , MONTHNAME(time) mon , COUNT(*) cnt FROM ACTIVITIES
WHERE MONTH(time) = MONTH(NOW() - INTERVAL 1 MONTH) GROUP by user_id, MONTH(time) having cnt=31) as x
Return 6
I want the ratio of query 1 and two. Means
18/6 . I am using MySQL
If you use both queries as CTEs, then it becomes relatively simple:
WITH q1
AS (SELECT Count(DISTINCT user_id) total_daily_active_user_group_month
FROM (SELECT user_id,
Monthname(TIME) mon,
Count(*) cnt
FROM activities
WHERE Month(TIME) = Month(Now() - interval 1 month)
GROUP BY user_id,
Month(TIME))),
q2
AS (SELECT Count(DISTINCT user_id) total_daily_active_user_group_month
FROM (SELECT user_id,
Monthname(TIME) mon,
Count(*) cnt
FROM activities
WHERE Month(TIME) = Month(Now() - interval 1 month)
GROUP BY user_id,
Month(TIME)
HAVING cnt = 31))
SELECT q1.total_daily_active_user_group_month /
q2.total_daily_active_user_group_month
AS result
FROM dual;
You commented that you got an error pointing to the WITH keyword; switch to two subqueries, then; simplified:
select a.value / b.value as result
from (select count(distinct user_id) value
from ... your 1st query goes here
) a,
(select count(distinct user_id) value
from ... your 2nd query goes here
) b;

MySQL - Count and GroupBy

I have this structure:
id| date_1 | date_2
---------------------
01|2017-01-01|2017-02-22
02|2017-01-02|2017-03-25
03|2017-02-10|2017-03-20
04|2017-03-11|2017-04-10
05|2017-03-15|2017-05-01
06|2017-03-20|2017-05-20
I would need this kind of result:
Month |Count(date_1)|Count(date_2)
---------------------------------
2017-01| 2 | 0
2017-02| 1 | 1
2017-03| 3 | 2
2017-04| 0 | 1
2017-05| 0 | 2
Now, I use this query (it works with only one date):
SELECT CONCAT(YEAR(date_1), '-', DATE_FORMAT(date_1,'%m')) AS month,
COUNT(*) AS items
FROM table
GROUP BY YEAR(date_1), MONTH(date_1)
ORDER BY date_1 DESC
You could union all the date values and then group and count them:
SELECT DATE_FORMAT(d, '%y-%m'), COUNT(*)
FROM (SELECT date_1 AS d FROM mytable
UNION ALL
SELECT date_2 FROM mytable) t
GROUP BY DATE_FORMAT(d, '%y-%m')
ORDER BY d DESC
To get the count of date_1 and date_2 in two different fields, with sub query:
SELECT DATE_FORMAT(temp1.d, '%y-%m'), COALESCE(d1count,0) AS date_1_count, COALESCE(d2count,0)AS date_2_count
FROM (
select date_1 as d from dates group by date_1
union all
select date_2 as d from dates group by date_2
) as temp1
LEFT JOIN (
select date_1, count(*) as d1count
from dates
group by DATE_FORMAT(date_1, '%y-%m')) as temp2
on DATE_FORMAT(temp2.date_1, '%y-%m') = DATE_FORMAT(temp1.d, '%y-%m')
LEFT JOIN (
select date_2, count(*) as d2count
from dates
group by DATE_FORMAT(date_2, '%y-%m')) as temp3
on DATE_FORMAT(temp3.date_2, '%y-%m') = DATE_FORMAT(temp1.d, '%y-%m')
GROUP BY DATE_FORMAT(temp1.d, '%y-%m')
Consider using subqueries behind SELECT
SELECT distinct DATE_FORMAT(t.d, '%y-%m'),
(
SELECT count(*)
FROM your_table as dd
where DATE_FORMAT(dd.date_1, '%y-%m') = DATE_FORMAT(t.d, '%y-%m')
) as count_date_1,
(
SELECT count(*)
FROM your_table as dd
WHERE DATE_FORMAT(dd.date_2, '%y-%m') = DATE_FORMAT(t.d, '%y-%m')
) as count_date_2
FROM
(
SELECT date_1 AS d FROM your_table
UNION ALL
SELECT date_2 as d FROM your_table
) as t
dbfiddle demo

MYSQL get total sum and sum between 2 date in 1 query

I am trying to get the total sum of a column and the sum of the same column between 2 dates in one query. is this possible?
My table looks like this:
uid|amount|date
The two queries i am trying to make one of:
SELECT sum(amount) as `keys` FROM tbl_keys WHERE uid = 1
SELECT sum(amount) as `keys` FROM tbl_keys WHERE uid = 1 AND YEAR(`date`) = YEAR(CURRENT_DATE)
AND MONTH(`date`) = MONTH(CURRENT_DATE)
You could use a UNION query:
SELECT 'All' AS cnt, sum(amount) as `keys` FROM tbl_keys WHERE uid = 1
UNION ALL
SELECT 'Current_month' AS cnt, sum(amount) as `keys`
FROM tbl_keys
WHERE
uid = 1
AND `date`<= last_day(current_date)
`date`>= current_date - interval (day(current_date)-1) day
(I prefer to use >= and <= on the date column, as it can make use of an index if present, while functions like MONTH() or YEAR() cannot, also I assume that date is a date columnd and that it doesn't contain time informations).
If you want the result in one row, you could use an inline query:
SELECT
(SELECT sum(amount) as `keys` FROM tbl_keys WHERE uid = 1) AS total,
(SELECT sum(amount) as `keys`
FROM tbl_keys
WHERE
uid = 1
AND `date`<= last_day(current_date)
`date`>= current_date - interval (day(current_date)-1) day
) AS current_month
Something like this:
SELECT sum(amount) as `keys`,
(
SELECT sum(t.amount)
FROM tbl_keys as t
WHERE t.uid = tbl_keys.uid AND YEAR(t.`date`) = YEAR(CURRENT_DATE)
AND MONTH(t.`date`) = MONTH(CURRENT_DATE)
) as `keys2`
FROM tbl_keys
WHERE uid = 1
SELECT sum(amount) AS `keys`
FROM (
SELECT amount FROM tbl_keys
UNION ALL
SELECT amount FROM tbl_keys
WHERE uid = 1
AND YEAR(`date`) = YEAR(CURRENT_DATE)
AND MONTH(`date`) = MONTH(CURRENT_DATE)
) AS new_table;
Using a UNION clause, you will get the desired output you want.
Use CASE to count only the amount for the specified date:
SELECT SUM(amount) AS `keys`,
SUM(CASE WHEN YEAR(`date`) = YEAR(CURRENT_DATE)
AND MONTH(`date`) = MONTH(CURRENT_DATE) THEN amount ELSE 0 END) AS 'keys2'
FROM tbl_keys
WHERE uid = 1
;
My guess is that this will run more efficient than a solution using UNION SELECT.

Mysql to select month-wise record even if data not exist

I wrote a query to get month-wise record in user table as follows
SELECT COUNT( `userID` ) AS total, DATE_FORMAT( `userRegistredDate` , '%b' ) AS
MONTH , YEAR( `userRegistredDate` ) AS year
FROM `users`
GROUP BY DATE_FORMAT( FROM_UNIXTIME( `userRegistredDate` , '%b' ) )
Output:
total MONTH year
---------------------------
3 May 2013
2 Jul 2013
--------------------------
Expected Output:
total MONTH year
---------------------------
0 Jan 2013
0 Feb 2013
0 Mar 2013
0 Apr 2013
3 May 2013
0 Jun 2013
2 Jul 2013
--------------------------
I need to show the record even if data not exist. How to do this?
I won't say much about efficiency as I have not tested it against other methods but without having a temp table this seem a fair way to go.
SELECT COUNT(u.userID) AS total, m.month
FROM (
SELECT 'Jan' AS MONTH
UNION SELECT 'Feb' AS MONTH
UNION SELECT 'Mar' AS MONTH
UNION SELECT 'Apr' AS MONTH
UNION SELECT 'May' AS MONTH
UNION SELECT 'Jun' AS MONTH
UNION SELECT 'Jul' AS MONTH
UNION SELECT 'Aug' AS MONTH
UNION SELECT 'Sep' AS MONTH
UNION SELECT 'Oct' AS MONTH
UNION SELECT 'Nov' AS MONTH
UNION SELECT 'Dec' AS MONTH
) AS m
LEFT JOIN users u
ON MONTH(STR_TO_DATE(CONCAT(m.month, ' 2013'),'%M %Y')) = MONTH(u.userRegistredDate)
AND YEAR(u.userRegistredDate) = '2013'
GROUP BY m.month
ORDER BY 1+1;
If you make the union based on a date format you can even reduce the work and load on the query.
SELECT COUNT(u.userID) AS total, DATE_FORMAT(merge_date,'%b') AS month, YEAR(m.merge_date) AS year
FROM (
SELECT '2013-01-01' AS merge_date
UNION SELECT '2013-02-01' AS merge_date
UNION SELECT '2013-03-01' AS merge_date
UNION SELECT '2013-04-01' AS merge_date
UNION SELECT '2013-05-01' AS merge_date
UNION SELECT '2013-06-01' AS merge_date
UNION SELECT '2013-07-01' AS merge_date
UNION SELECT '2013-08-01' AS merge_date
UNION SELECT '2013-09-01' AS merge_date
UNION SELECT '2013-10-01' AS merge_date
UNION SELECT '2013-11-01' AS merge_date
UNION SELECT '2013-12-01' AS merge_date
) AS m
LEFT JOIN users u
ON MONTH(m.merge_date) = MONTH(u.userRegistredDate)
AND YEAR(m.merge_date) = YEAR(u.userRegistredDate)
GROUP BY m.merge_date
ORDER BY 1+1;
Live DEMO of both queries.
You may need a table to hold every "month" record. A temp table can do the trick:
drop table if extists temp_months;
create temporary table temp_months
month date,
index idx_date(month);
insert into temp_months
values ('2013-01-31'), ('2013-02-28'), ...
And now, you can left join your data with this newly created temp table:
SELECT
COUNT( `userID` ) AS total,
DATE_FORMAT( m.month , '%b' ) AS
MONTH ,
YEAR( m.month ) AS year
FROM
months as m
left join `users` as u on m.month = last_day(FROM_UNIXTIME(`userRegistredDate`, '%b' )
GROUP BY
last_day(m.month);
Notice that you can put the temp table creation (and fill) in a stored procedure.
I use last_day for simplicity, but you are free to use any date in the month that you like, if you join it correctly.
Hope this helps

Same month two different SUMS

I'm trying to get different Sums for same month on same Year, just to get sums by different types. Tried using this code:
SELECT a.invoice_type, year( a.date ) AS Year,
date_format( a.date, '%M' ) AS `month` ,
Sum( x.amount * x.price ) AS sum FROM records x
JOIN paper_invoice a ON x.invoice_id = a.invoice_id
WHERE year( a.date ) = '2012'
GROUP BY a.invoice_type, Year( a.date ) , Month( a.date ) LIMIT 0 , 30
but it gives results in different rows:
http://www.part.lt/img/1505f0f13172922150febede85ddbf0925.png
But I need it to look like:
Year | Month | SUM_GRYNAIS | SUM_PAVEDIMU
2012 | January | 7597.14997705445 | 58740.2800849304
and ETC.
Try this:
SELECT Year, Month,
MAX(CASE WHEN invoice_type = 'GRYNAIS' THEN sum END) As Sum_GRYNAIS
MAX(CASE WHEN invoice_type = 'PAVEDIMU' THEN sum END) As SUM_PAVEDIMU
FROM
(
SELECT a.invoice_type, year( a.date ) AS Year,
date_format( a.date, '%M' ) AS `month` , Sum( x.amount * x.price ) AS sum
FROM records x JOIN paper_invoice a ON x.invoice_id = a.invoice_id
WHERE year( a.date ) = '2012' GROUP BY a.invoice_type, Year( a.date ) ,
Month( a.date ) LIMIT 0 , 30
)
GROUP BY Year, Month
Because each month has a different value. Try Group By on just the field year.
You are basically looking for PIVOT. MySql doesn't have a PIVOT function but you can still accomplish this. Here is an example of a PIVOT in MySql:
http://www.artfulsoftware.com/infotree/queries.php#78