how count different values per each day ? and the total value for each day? in one request.
key1 | key2 | tdate | tview
1 | 20161123454647 | 2016-11-23 11:11:11 | view1
2 | 20161123454648 | 2016-11-23 11:11:11 | view2
3 | 20161122454649 |2016-11-22 11:11:11 | view2
4 | 20161122454650 |2016-11-22 11:11:11 | view1
5 | 20161122454653 |2016-11-22 11:11:11 | view2
6 | 20161122454661 |2016-11-22 11:11:11 | view2
7 | 20161121454622 |2016-11-21 11:11:11 | view3
8 | 20161121454679 |2016-11-21 11:11:11 | view1
9 | 20161121454684 |2016-11-21 11:11:11 | view3
I found to count the total of all values of tview per day :
SELECT DATE(tdate) Date, COUNT(DISTINCT tview) totalOfViews FROM mytable GROUP BY DATE(tdate)
I have a key (key2) which the concatenation of date and the number of a render because I don't want to hive two same render in the same day.
It's most easy for me when I insert a new render with 'INSERT ON DUPLICATE key2 UPDATE'. I update just the number of view with one request. I don't know 'INSET ON DUPLICATE' <2 differents keys> UPDATE :newview. Interesting question too ;-)
The date is a timestamp in my table.
I use php 7, MySQL and PDO to do statement.
One of interesting output:
day | totaView1 | totalView2 | totalView3 | totalView1+view2 |totalOfViews
2016-11-23 | 1 | 1 | 0 | 2 | 2
2016-11-22 | 1 | 3 | 0 | 4 | 4
2016-11-21 | 1 | 0 | 2 | 1 | 3
After i found to range date of request and compare évolution of number view per day. Example:
Day (currentmonth) | totaView1 | totalView1 (lastmonth) |totalOfViews
Is the "alter table" can do this result?
One possibility is to use conditional aggregation:
SELECT DATE(tdate) AS day,
SUM(CASE WHEN tview = 'view1' THEN 1 ELSE 0 END) AS totaView1,
SUM(CASE WHEN tview = 'view2' THEN 1 ELSE 0 END) AS totaView2,
SUM(CASE WHEN tview = 'view3' THEN 1 ELSE 0 END) AS totaView3,
SUM(CASE WHEN tview = 'view1' OR tview = 'view2'
THEN 1 ELSE 0 END) AS totaView1Or2,
COUNT(*) AS totalOfViews
FROM mytable
GROUP BY DATE(tdate)
Related
I have a table consisting of result, name and created_at like :
id | name | result | created_at
1 | Sam | 1 | 2018-07-12 05:08:04
2 | Tam | 1 | 2018-07-12 06:08:04
3 | Qam | 0 | 2018-07-12 07:08:04
4 | Yam | 1 | 2018-09-12 04:08:04
5 | Xam | 0 | 2018-09-12 06:08:04
6 | Lam | 0 | 2018-11-12 07:08:04
(the 1 represents pass where as 0 represent fails) I want to group the data by created at date which displays the count of result success or failed in seperate colums like:
fail | pass | created_at
0 | 2 | 2018-07-12 05:08:04
1 | 1 | 2018-09-12 04:08:04
1 | 0 | 2018-11-12 07:08:04
I could count the value of just pass or fail with this query: select count(result) from call_history where result = 1 GROUP BY DATE(created_at), but wasn't able to provide double where clause for different rows.
You can use a case expression to return a non-null result only for successes/failures, and then use count, which skips nulls:
SELECT COUNT(CASE result WHEN 0 THEN 1 END) AS fail,
COUNT(CASE result WHEN 1 THEN 1 END) AS pass,
created_at
FROM call_history
GROUP BY created_at
I would write this as:
SELECT SUM(1 - result) as fail,
SUM(result as pass)
created_at
FROM call_history
GROUP BY created_at;
I have the following table
+-----+------------------+-------------+
| id | name |month_1 |
+-----+------------------+-------------+
| 1 | anna | 15 |
| 2 | bin | 20 |
+-----+------------------+-------------+
When I make a selection I want to add one more column.
For example
SELECT id,name, money as month_1 FROM test where month(day)='1';
And I want to add a column, something like this:
SELECT id,name, money as month_1,money as month_2
FROM test
where where month(day)='1',where month(day)='2'
+-----+------------------+-------------+------------+
| id | name | month_1 |month_2 |
+-----+------------------+-------------+------------+
| 1 |anna | 15 | 10 |
| 2 | bin | 20 | 0 |
+-----+------------------+-------------+------------+
You can use conditional aggregation:
SELECT id,name,
SUM(CASE WHEN month(day) = 1 THEN money ELSE 0 END) as month_1,
SUM(CASE WHEN month(day) = 2 THEN money ELSE 0 END) as month_2
FROM test
GROUP BY id, name;
You may or may not want to include the month and year in the aggregation.
I have a table of sign-ins for people who are logging time on different projects and I need to compile a report of which days each project was worked on.
My table looks something like this:
id | project | time_in
----------------------------------
1 | 1 | 2014-12-07 05:00:00
2 | 2 | 2014-12-08 06:00:00
3 | 1 | 2014-12-05 14:00:00
4 | 3 | 2014-12-07 08:30:00
5 | 2 | 2014-12-07 12:00:00
6 | 1 | 2014-12-08 05:00:00
7 | 2 | 2014-12-05 06:00:00
8 | 1 | 2014-12-06 14:00:00
9 | 3 | 2014-12-08 08:30:00
10 | 2 | 2014-12-06 12:00:00
time_in is of type TIMESTAMP.
What I need to figure out is, given a date range (e.g. December 5 - 8), which days of the week each project was worked on. I'm totally flexible on the query, i.e. I can generate the query using a loop, and I'm also flexible on how the result set looks, so long as I can parse it to get the information I need. For example, maybe:
project | days
-----------------------------------------------------
1 | 2014-12-07,2014-12-08,2014-12-05,2014-12-06
2 | 2014-12-08,2014-12-07,2014-12-05,2014-12-06
3 | 2014-12-07,2014-12-08
Or better yet:
project | d0 | d1 | d2 | d3
---------------------------
1 | 1 | 1 | 1 | 1
2 | 1 | 1 | 1 | 1
3 | 0 | 0 | 1 | 1
I honestly have no idea where to even begin on a query like this, if it's even possible.
You could use group_concat to achieve your initial results:
select project, group_concat(date(time_in) order by time_in)
from yourtable
group by project
SQL Fiddle Demo
If you want additional columns, you could use max with case:
select project,
max(case when date(time_in) = '2014-12-05' then 1 else 0 end) d0,
max(case when date(time_in) = '2014-12-06' then 1 else 0 end) d1,
max(case when date(time_in) = '2014-12-07' then 1 else 0 end) d2,
max(case when date(time_in) = '2014-12-08' then 1 else 0 end) d3
from yourtable
group by project
More Fiddle
I'm trying create an SQL query to resolve my problem.
My Table:
+----+---------------------+-------+
| id | date | value |
+----+---------------------+-------+
| 1 | 2014-10-10 05:10:10 | 10 |
+----+---------------------+-------+
| 2 | 2014-10-10 09:10:10 | 20 |
+----+---------------------+-------+
| 3 | 2014-10-10 15:10:10 | 30 |
+----+---------------------+-------+
| 4 | 2014-10-10 23:10:10 | 40 |
+----+---------------------+-------+
| 5 | 2014-10-11 08:10:10 | 15 |
+----+---------------------+-------+
| 6 | 2014-10-11 09:10:10 | 25 |
+----+---------------------+-------+
| 7 | 2014-10-11 10:10:10 | 30 |
+----+---------------------+-------+
| 8 | 2014-10-11 23:10:10 | 40 |
+----+---------------------+-------+
I want to sum value in groups by days and this days in three sub groups like a 'morning'(06:00 - 12:00), 'afternoon'(12:00 - 18:00) and 'night'(00:00 - 06:00 and 18:00 - 24:00).
something like this:
+------------+-------+---------+-----------+-------+
| date | value | morning | afternoon | night |
+------------+-------+---------+-----------+-------+
| 2014-10-10 | 100 | 20 | 30 | 50 |
+------------+-------+---------+-----------+-------+
| 2014-10-11 | 110 | 70 | 0 | 40 |
+------------+-------+---------+-----------+-------+
You could use a couple of sums over case expressions:
SELECT DAY(`date`) AS `date`
SUM(CASE WHEN HOUR(`date`) BETWEEN 6 AND 12 THEN value ELSE 0 END) AS `morning`,
SUM(CASE WHEN HOUR(`date`) BETWEEN 12 AND 18 THEN value ELSE 0 END) AS `afternoon`,
SUM(CASE WHEN HOUR(`date`) < 6 OR HOUR(`date`) > 18 THEN value ELSE 0 END) AS `evening`
FROM my_table
GROUP BY DAY(`date`)
There are multiple ways to go about this, but for myself I'd do it by first extracting the pseudo information in a CROSS APPLY, and then grouping on this information.
I believe this offers significant readibility benefits, and allows you to re-use any calculations in other clauses. For example, you have centralised the grouping mechanism, meaning that you only need to change it in the one place rather than in the select and the group by. Similarly, you could add "extraData.Morning = 1" to a WHERE clause rather than re-writing the calculation for mornings.
For example:
CREATE TABLE #TestData (ID INT, Data DATETIME, Value INT)
INSERT INTO #TestData (ID, Data, Value) VALUES
(1 ,'2014-10-10 05:10:10' ,10)
,(2 ,'2014-10-10 09:10:10' ,20)
,(3 ,'2014-10-10 15:10:10' ,30)
,(4 ,'2014-10-10 23:10:10' ,40)
,(5 ,'2014-10-11 08:10:10' ,15)
,(6 ,'2014-10-11 09:10:10' ,25)
,(7 ,'2014-10-11 10:10:10' ,30)
,(8 ,'2014-10-11 23:10:10' ,40)
SELECT
extraData.DayComponent
,SUM(td.Value)
,SUM(CASE WHEN extraData.Morning = 1 THEN td.Value ELSE 0 END) AS Morning
,SUM(CASE WHEN extraData.Afternoon = 1 THEN td.Value ELSE 0 END) AS Afternoon
,SUM(CASE WHEN extraData.Night = 1 THEN td.Value ELSE 0 END) AS Night
FROM #TestData td
CROSS APPLY (
SELECT
DATEADD(dd, 0, DATEDIFF(dd, 0, td.Data)) AS DayComponent
,CASE WHEN DATEPART(HOUR, td.Data) BETWEEN 6 AND 12 THEN 1 ELSE 0 END AS Morning
,CASE WHEN DATEPART(HOUR, td.Data) BETWEEN 12 AND 18 THEN 1 ELSE 0 END AS Afternoon
,CASE WHEN DATEPART(HOUR, td.Data) BETWEEN 0 AND 6
OR DATEPART(HOUR, td.Data) BETWEEN 18 AND 24 THEN 1 ELSE 0 END AS Night
) extraData
GROUP BY
extraData.DayComponent
DROP TABLE #TestData
I'm using two tables in the database.
The first contains data related to the successful and unsuccessful payments while the second table contains data regarding the status of services.
The result of the query should combine both tables and as a result list the successful and unsuccessful payments grouped by the days as well as the status of services grouped by days.
First table looks like:
id | charged | date
-----------------------------
8 | OK | 2011-12-03
7 | OK | 2011-12-03
9 | NO | 2011-12-03
11 | OK | 2011-12-04
14 | NO | 2011-12-04
The second table looks like:
id | status | date
--------------------------
8 | 1 | 2011-12-03
9 | 1 | 2011-12-03
11 | 0 | 2011-12-04
12 | 0 | 2011-12-04
14 | 1 | 2011-12-04
The correct query result should be:
date | not_charged | charged | status_1 | status_0
-----------------------------------------------------------
2011-12-04 | 1 | 1 | 1 | 2
2011-12-03 | 1 | 2 | 2 | 0
The query that I've tried looks like this:
SELECT i.date, SUM(
CASE WHEN i.charged = 'NO'
THEN 1 ELSE 0 END ) AS not_charged, SUM(
CASE WHEN i.charged = 'OK'
THEN 1 ELSE 0 END ) AS charged, SUM(
CASE WHEN s.status = '1'
THEN 1 ELSE 0 END ) AS status_1, SUM(
CASE WHEN s.status = '0' THEN 1 ELSE 0 END ) AS status_0
FROM charge i INNER JOIN status s ON s.date = i.date
GROUP BY i.date
But I get the wrong result that looks like this
date | not_charged | charged | status_1 | status_0
---------------------------------------------------------
2011-12-04 | 3 | 3 | 2 | 4
2011-12-03 | 2 | 4 | 6 | 0
What I'm doing wrong and how can I get the correct result?
Thanks for all suggestions.
Try this one -
SELECT date,
SUM(IF(charged = 'NO', 1, 0)) not_charged,
SUM(IF(charged = 'OK', 1, 0)) charged,
SUM(IF(status = 1, 1, 0)) status_1,
SUM(IF(status = 0, 1, 0)) status_0
FROM (
SELECT date, charged, NULL status FROM charge
UNION ALL
SELECT date, NULL charged, status FROM status
) t
GROUP BY date DESC;
+------------+-------------+---------+----------+----------+
| date | not_charged | charged | status_1 | status_0 |
+------------+-------------+---------+----------+----------+
| 2011-12-04 | 1 | 1 | 1 | 2 |
| 2011-12-03 | 1 | 2 | 2 | 0 |
+------------+-------------+---------+----------+----------+
This assumes the ID columns related that service status and payment status together...
SELECT
COALESCE(charge.date, status.date) AS date,
SUM(CASE WHEN charge.charged = 'NO' THEN 1 ELSE 0 END) AS not_charged,
SUM(CASE WHEN charge.charged = 'OK' THEN 1 ELSE 0 END) AS charged,
SUM(CASE WHEN status.status = '0' THEN 1 ELSE 0 END) AS status_0,
SUM(CASE WHEN status.status = '1' THEN 1 ELSE 0 END) AS status_1
FROM
charge
FULL OUTER JOIN
status
ON charge.id = status.id
GROUP BY
COALESCE(charge.date, status.date)
Note, I'm note sure how you want to deal with 7 (No status record) and 12 (no charge record). This currently just counts what is there.
Alternatively, if you don't want to related the records by ID, you can still relate by date but you need to change your logic.
At present you're getting this, because you only relate by date...
id | charged | date id | status | date
----------------------------- --------------------------
8 | OK | 2011-12-03 8 | 1 | 2011-12-03
8 | OK | 2011-12-03 9 | 1 | 2011-12-03
7 | OK | 2011-12-03 8 | 1 | 2011-12-03
7 | OK | 2011-12-03 9 | 1 | 2011-12-03
9 | NO | 2011-12-03 8 | 1 | 2011-12-03
9 | NO | 2011-12-03 9 | 1 | 2011-12-03
11 | OK | 2011-12-04 11 | 0 | 2011-12-04
11 | OK | 2011-12-04 12 | 0 | 2011-12-04
11 | OK | 2011-12-04 14 | 1 | 2011-12-04
14 | NO | 2011-12-04 11 | 0 | 2011-12-04
14 | NO | 2011-12-04 12 | 0 | 2011-12-04
14 | NO | 2011-12-04 14 | 1 | 2011-12-04
Instead you need to consolidate the data down to 1 per date per table, then join...
SELECT
COALESCE(charge.date, status.date) AS date,
charge.not_charged,
charge.charged,
status.status_0,
status.status_1
FROM
(
SELECT
date,
SUM(CASE WHEN charged = 'NO' THEN 1 ELSE 0 END) AS not_charged,
SUM(CASE WHEN charged = 'OK' THEN 1 ELSE 0 END) AS charged
FROM
charge
GROUP BY
date
)
AS charge
FULL OUTER JOIN
(
SELECT
date,
SUM(CASE WHEN charged = '0' THEN 1 ELSE 0 END) AS status_0,
SUM(CASE WHEN charged = '1' THEN 0 ELSE 1 END) AS status_1
FROM
status
GROUP BY
date
)
AS status
ON charge.date = status.date
There are other methods, but hopefully this explains a bit for you.
I suggest using a UNION ALL:
select date,
coalesce(sum(not_charged),0) not_charged,
coalesce(sum(charged),0) charged,
coalesce(sum(status_1),0) status_1,
coalesce(sum(status_0),0) status_0
from (select date,
case charged when 'NO' then 1 end not_charged,
case charged when 'OK' then 1 end charged,
0 status_1,
0 status_0
from charge
union all
select date,
0 not_charged,
0 charged,
case status when '1' then 1 end status_1,
case status when '0' then 1 end status_0
from status) sq
group by date