Mysql Join query with count table records with same date - mysql

Hello i am having two different table with same field created_date (datetime)
now i want records which counts daywise records with joining table i have done for individual counting as below query :
SELECT DATE(created_date), COUNT(*) FROM table1 GROUP BY DAY(created_date)
SELECT DATE(created_date), COUNT(*) FROM table2 GROUP BY DAY(created_date)
and i am getting results for individuals something like this:
RESULT I NEED :
DATE(created_date) count(table1) count(table2)
2016-12-01 10 3
2016-12-02 1 0
2016-12-05 1 0
2016-11-29 1 0
2016-11-30 4 1
Now i just want to join these result WITH INDIVIDUAL VIEW COUNT ACCORDING TO TABLE can anyone please help me out with this profile....

First take a UNION between your two tables, then use conditional aggregation to determine the counts for each of the two tables. Note that I introduce a field called table_name to keep track of data from each of the two tables.
SELECT t.created_date,
SUM(CASE WHEN t.table_name = 'one' THEN 1 ELSE 0 END) AS count_table_one,
SUM(CASE WHEN t.table_name = 'two' THEN 1 ELSE 0 END) AS count_table_two
FROM
(
SELECT DATE(created_date) AS created_date, 'one' AS table_name
FROM table1
UNION ALL
SELECT DATE(created_date), 'two'
FROM table2
) t
GROUP BY t.created_date
I used DATE consistently everywhere to make the query correct.

Try This:
SELECT created_date, sum(countTable1) countTable1,
sum(countTable2) countTable2
FROM (
SELECT DATE(created_date) created_date, COUNT(*) countTable1, NULL countTable2
FROM table1 GROUP BY DAY(created_date)
UNION ALL
SELECT DATE(created_date) created_date, NULL, COUNT(*) countTable2
FROM table2 GROUP BY DAY(created_date)) t GROUP BY t.created_date

You have a problem in your queries, you are grouping by DAY(date) and showing 'date' so the result will be first date with day(date), yet repeating it to avoid misunderstanding :)
select IFNULL(A.cd, B.cd), A.cnt, B.cnt from
(SELECT DAY(created_date) d, DATE(created_date) cd, COUNT(*) cnt
FROM table1 GROUP BY DAY(created_date)) as A
LEFT JOIN
(SELECT DAY(created_date) d, DATE(created_date) cd , COUNT(*) cnt
FROM table2 GROUP BY DAY(created_date)) B ON B.d = A.d

Its not too hard just use union if no need to allow duplicate row else use union all for all(means allow duplicate as well).
SELECT DATE(created_date), COUNT(*) FROM table1 GROUP BY DAY(created_date)
UNION
SELECT DATE(created_date), COUNT(*) FROM table2 GROUP BY DAY(created_date)

SELECT T.create_date,ISNULL(T.count,0)AS Counttable1,ISNULL(X.count,0)AS Counttable2 FROM(SELECT DATE(created_date) AS create_date,COUNT(*) as count FROM table1 GROUP BY DAY(created_date)) AS T LEFTJOIN(SELECT DATE(created_date) AS create_date, COUNT(*) as count FROM table2 GROUP BY DAY(created_date))AS X ON T.create_date=X.create_date

You actually need a SQL UNION. JOIN natuarually eliminate counts becuase the maytch fields. I.e. if you had 2016-12-01 in both table1 andtable2 then a JOIN on created_date would give you a count of 1 instead of a count of 2.
SELECT DATE(total.created_date), COUNT(*)
FROM (
SELECT created_date FROM table1
UNION ALL
SELECT created_date FROM table2) as total
GROUP BY total.created_date
HERE you simply union the two tables since they have a matching column name. Then you get back every date from both tables. That is in the inner query. The outer query then does the counting.
Hope that makes sense.

Related

MYSQL - Select Only Records Where Previous Record Column Data Differs

Hoping this is possible with just sql. I have a query that returns a data set with time_stamp and hash_index columns. Basically something to the effect of:
1 1583365548 6ff11ad5536f28d66098f6d74f97d877
2 1583365554 6ff11ad5536f28d66098f6d74f97d877
3 1583365556 6ff11ad5536f28d66098f6d74f97d877
4 1583365562 a2e99acb2540d49955ef93fb2684ac25
5 1583365571 a2e99acb2540d49955ef93fb2684ac25
6 1583365572 a2e99acb2540d49955ef93fb2684ac25
7 1583365574 a2e99acb2540d49955ef93fb2684ac25
8 1583365578 a2e99acb2540d49955ef93fb2684ac25
9 1583365580 a2e99acb2540d49955ef93fb2684ac25
What I want to do is further filter this query to only include the record if the hash_index differs from the previous record. Is this something I can do without having to dump it into PHP and loop through it?
My current query is below:
SELECT
(#cnt:=#cnt + 1) AS row_number,
time_stamp,
MD5(GROUP_CONCAT(CONCAT(user_state_name,
option_id,
option_code,
item_id,
item_code))) AS hash_index
FROM
user_state
WHERE
user_id = 2
GROUP BY
time_stamp;
What is with a query like this:
SELECT t1.*
FROM user_state t1
LEFT JOIN user_state t2 ON t1.id-1 = t2.id
WHERE t1.hash_index <> t2.hash_index;
If you want to filter out adjacent duplicates, I would just use lag() and dispense with hashing and aggregation:
SELECT us.*
FROM (SELECT us.*,
LAG(time_stamp) OVER (PARTITION BY user_id ORDER BY time_stamp) as prev_ts,
LAG(time_stamp) OVER (PARTITION BY user_id, user_state_nae, option_id, option_code, item_id, item_code ORDER BY time_stamp) as prev_ts_values
FROM user_state us
WHERE user_id = 2
) t
WHERE prev_ts_values is null or prev_ts_values <> prev_ts;
You can select whichever rows you want.

Aggregating a table by multiple different column filters

I have a query that groups a table by a certain column and provides some aggregate data based on some filtering. Currently, the only way I know how to achieve the query is to use a number of subqueries, which seems inefficient. Let's assume I have the following table:
user_id event_type value
1 click 4
2 click 2
1 click 1
4 close 5
2 open 3
I want to group the data by user_id and aggregate the following information: max_value, min_click_value. Based on the example table able, this is the result I'd like to see:
user_id max_value min_click_value
1 4 1
2 3 2
4 5 null
Is there a way to accomplish this without subqueries? What I have so far is this, which works, but it feels pretty inefficent:
SELECT t1.user_id, max_value, min_click_value
(SELECT user_id, MAX(value) as max_value
FROM my_table
GROUP BY user_id) as t1
LEFT JOIN
(SELECT user_id, MIN(value) as min_click_value
FROM my_table
WHERE event_type = "click"
GROUP BY user_id) as t2
WHERE t1.user_id = t2.user_id
Conditional aggregation should work here:
SELECT
user_id,
MAX(value) AS max_value,
MIN(CASE WHEN event_type = 'click' THEN value END) AS min_click_value
FROM yourTable
GROUP BY
user_id;
Use conditional aggregation:
select user_id, max(value) as max_value
min(case when event_type = 'click' then value end) as min_click_value
from my_table
group by user_id;

Select how many rows up to a date

having a list of people like:
name date_of_birth
john 1987-09-08
maria 1987-09-08
samuel 1987-09-09
claire 1987-09-10
jane 1987-09-10
rose 1987-09-12
...
How can I get a result view using SQL of how many people are born up to that date, like the output for that table should be:
date count
1987-09-08 2
1987-09-09 3
1987-09-10 5
1987-09-11 5
1987-09-12 6
...
Thanks!
Here is another way, in addition to Gordon's answer. It uses joins:
SELECT
t1.date_of_birth,
COUNT(*) AS count
FROM (SELECT DISTINCT date_of_birth FROM yourTable) t1
INNER JOIN yourTable t2
ON t1.date_of_birth >= t2.date_of_birth
GROUP BY
t1.date_of_birth;
Note: I left out a step. Apparently you also want to report missing dates. If so, then you may replace what I aliased as t1 with a calendar table. For the sake of demonstration, you can inline all the dates:
SELECT
t1.date_of_birth,
COUNT(*) AS count
FROM
(
SELECT '1987-09-08' AS date_of_birth UNION ALL
SELECT '1987-09-09' UNION ALL
SELECT '1987-09-10' UNION ALL
SELECT '1987-09-11' UNION ALL
SELECT '1987-09-12'
) t1
LEFT JOIN yourTable t2
ON t1.date_of_birth >= t2.date_of_birth
GROUP BY
t1.date_of_birth;
Demo
In practice, your calendar table would be a bona fide table which just contains all the dates you want to appear in your result set.
One method is a correlated subquery:
select dob.date_of_birth,
(select count(*) from t where t.date_of_birth <= dob.date_of_birth) as running_count
from (select distinct date_of_birth from t) dob;
This is not particularly efficient. If your data has any size, variables are better (or window functions if you are using MySQL 8.0):
select date_of_birth,
(#x := #x + cnt) as running_count
from (select date_of_birth, count(*) as cnt
from t
group by date_of_birth
order by date_of_birth
) dob cross join
(select #x := 0) params;
Use subquery with correlation approach :
select date_of_birth, (select count(*)
from table
where date_of_birth <= t.date_of_birth
) as count
from table t
group by date_of_birth;

How do I find duplicate values across multiple columns in Mysql?

I have a table like this
I want to check the all rows in Column A with column B and get the count of duplicates.
For example, I want to get the
count of 12 as 3(2 times in A+1 time in B)
count of 11 as 2(2 times in A+0 time in B)
count of 13 as 2(1 time in A+0 time in B)
How can I acheive it?
You can calculate the total occurrences from a union all. A where clause can show only the values that occur in the A column:
select nr
, count(*)
from (
select A as nr
from YourTable
union all
select B
from YourTable
) sub
where nr in -- only values that occur at least once in the A column
(
select A
from YourTable
)
group by
nr
having count(*) > 1 -- show only duplicates
You can combine all values in A and B then do the group by.
Then only select those values found in column A.
Select A, count(A) as cnt
From (
Select A
from yourTable
Union All
Select B
from yourTable) t
Where t.A in
(select distinct A from yourTable)
Group by t.A
Order by t.A;
Result:
A cnt
11 2
12 3
13 1
See demo: http://sqlfiddle.com/#!9/9fcfe9/3

Using SUM() without grouping the results

I already read (this), but couldn't figure out a way to implement it to my specific problem. I know SUM() is an aggregate function and it doesn't make sense not to use it as such, but in this specific case, I have to SUM() all of the results while maintaining every single row.
Here's the table:
--ID-- --amount--
1 23
2 11
3 8
4 7
I need to SUM() the amount, but keep every record, so the output should be like:
--ID-- --amount--
1 49
2 49
3 49
4 49
I had this query, but it only sums each row, not all results together:
SELECT
a.id,
SUM(b.amount)
FROM table1 as a
JOIN table1 as b ON a.id = b.id
GROUP BY id
Without the SUM() it would only return one single row, but I need to maintain all ID's...
Note: Yes this is a pretty basic example and I could use php to do this here,but obviously the table is bigger and has more rows and columns, but that's not the point.
SELECT a.id, b.amount
FROM table1 a
CROSS JOIN
(
SELECT SUM(amount) amount FROM table1
) b
You need to perform a cartesian join of the value of the sum of every row in the table to each id. Since there is only one result of the subselect (49), it basically just gets tacked onto each id.
With MS SQL you can use OVER()
select id, SUM(amount) OVER()
from table1;
select id, SUM(amount) OVER()
from (
select 1 as id, 23 as amount
union all
select 2 as id, 11 as amount
union all
select 3 as id, 8 as amount
union all
select 4 as id, 7 as amount
) A
--- OVER PARTITION ID
PARTITION BY which is very useful when you want to do SUM() per MONTH for example or do quarterly reports sales or yearly...
(Note needs distinct it is doing for all rows)
select distinct id, SUM(amount) OVER(PARTITION BY id) as [SUM_forPARTITION]
from (
select 1 as id, 23 as amount
union all
select 1 as id, 23 as amount
union all
select 2 as id, 11 as amount
union all
select 2 as id, 11 as amount
union all
select 3 as id, 8 as amount
union all
select 4 as id, 7 as amount
) OverPARTITIONID
Join the original table to the sum with a subquery:
SELECT * FROM table1, (SELECT SUM(amount) FROM table1 AS amount) t
This does just one sum() query, so it should perform OK:
SELECT a.id, b.amount
FROM table1 a
cross join (SELECT SUM(amount) as amount FROM table1 AS amount) b
in case someone else has the same problem and without joining we can do the following
select *
,totcalaccepted=(select sum(s.acceptedamount) from cteresult s)
, totalpay=(select sum(s.payvalue) from cteresult s)
from cteresult t
end
Using Full Join -
case when you need sum of amount field from tableB and all data from tableA on behalf of id match.
SELECT a.amount, b.* FROM tableB b
full join (
select id ,SUM(amount) as amount FROM tableA
where id = '1' group by id
) a
on a.id = b.id where a.id ='1' or b.id = '1' limit 1;