Transform datas in MySQL - mysql

I've got a query like this
select company, extract(week from date) as week, sum(value)
from temporary GROUP BY company,yearweek(date)
and after I got a view
Company | Week | Value
Dunaferr | 1 | 310
Dunaferr | 2 | 220
Dunaferr | 3 | 310
Pentele-Invest| 1 | 450
Pentele-Invest| 2 | 543
Pentele-Invest| 3 | 344
Finally what I want to is a table which one is sums the values weekly which is ordered by the company names
company_name | week1 | week2 | week3 | week4 ...
dunaferr | 35000 | 36000 | 28000 | 3411
pentele | 34000 | 255000 | 3341 | 3433
And I know there is a way to use pivoting but I don't know how to do it.

select szallito_nev,
sum(case extract(week from beerkezes_datuma) when '1' then merlegelt_suly else 0 end) as 'Het 1',
sum(case extract(week from beerkezes_datuma) when '2' then merlegelt_suly else 0 end) as 'Het 2',
sum(case extract(week from beerkezes_datuma) when '3' then merlegelt_suly else 0 end) as 'Het 3',
from 2013_backup GROUP BY szallito_nev with rollup;
i'll tried this one its work well but not so elegant way to do it:S becouse i have to go throw all the weeks of the year. probably theres a way to do it with loop

Related

Mysql display query data and count

Just an amateur here needing a little help.
I have a table named tbl_inspection_areas.area_description
columns 'area_description' and 'display_tab'.
I want a query that returns 'area_description','display_tab' and the number of times each display tab occurs.
Like in the drawing below.
| tbl_inspection_areas.area_description | tbl_inspection_areas.display_tab | count |
_____________________________________________________________________________________________
| engine | 38 | 2 |
| transmission | 38 | |
| interior | 39 | 1 |
| wheels | 40 | 3 |
| glass | 40 | |
| lights | 40 | |
This is the best I have come up with, but it only displays 3 rows and the count is in 3 seperate columns.
Any help would be great.
SELECT
tbl_inspection_areas.area_description,
tbl_inspection_areas.display_tab,
SUM(CASE WHEN tbl_inspection_areas.display_tab = '38' THEN 1 ELSE 0 END) AS count1,
SUM(CASE WHEN tbl_inspection_areas.display_tab = '39' THEN 1 ELSE 0 END) AS count2,
SUM(CASE WHEN tbl_inspection_areas.display_tab = '40' THEN 1 ELSE 0 END) AS count3,
SUM(CASE WHEN tbl_inspection_areas.display_tab = '46' THEN 1 ELSE 0 END) AS count4
FROM tbl_inspection_areas
GROUP BY tbl_inspection_areas.display_tab
SELECT
tbl_inspection_areas.area_description,
tbl_inspection_areas.display_tab,
COUNT(tbl_inspection_areas.display_tab)
FROM tbl_inspection_areas
GROUP BY tbl_inspection_areas.area_description,
tbl_inspection_areas.display_tab,

count and sum different values per each day

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)

MySQL How to convert second group by parameter results as a column?

The following MySQL query result set repeats MerchantID:
select MerchantID,Category,SUM(Amount)
group by MerchantID,Category
from merchants
This will produce the following result:
MerchantID | Category | Total |
1 | gold | 450 |
1 | silver | 600 |
2 | gold | 1120 |
2 | bronze | 200 |
I want to get the result set like below:
MerchantID | gold | silver | bronze |
1 | 450 | 600 | 0 |
2 | 1120 | 0 | 200 |
I tried many queries but could not get such result. Please provide a solution for my problem. Thanks.
Use conditional aggregation:
select MerchantID,
SUM(CASE WHEN Category = 'gold' THEN Total ELSE 0 END) AS gold,
SUM(CASE WHEN Category = 'silver' THEN Total ELSE 0 END) AS silver,
SUM(CASE WHEN Category = 'bronze' THEN Total ELSE 0 END) AS bronze
from merchants
group by MerchantID
Demo here
You can use this code for example:
SELECT m.merchantId
sum(if(m.Category='gold',m.total,null)) as gold,
sum(if(m.Category='silver',m.total,null)) as silver,
sum(if(m.Category='bronze',m.total,null)) as bronze
FROM merchants m
GROUP BY m.merchantId

MySql query group by day and by time

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

Mysql inner join query

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