I have two tables similar to these:
Table: case
---------------------------------------------------
| id | company | managed | time | client |
---------------------------------------------------
| 1 | apple | yes | 1412643785 | no |
---------------------------------------------------
| 2 | barilla | no | 1412643785 | no |
---------------------------------------------------
| 3 | google | no | 1412643785 | yes |
---------------------------------------------------
| 4 | google | yes | 1412643785 | yes |
---------------------------------------------------
| 5 | google | no | 1412643785 | yes |
---------------------------------------------------
Table: language
---------------------------
| id | company | lang |
---------------------------
| 1 | apple | EN |
---------------------------
| 2 | barilla | IT |
---------------------------
| 3 | google | EN |
---------------------------
I have create statistics/graphics from this tablet, the I extract the following information for each month:
* Number of cases of clients per month
* Number of cases managed per month
* Total number of cases per month
* Number of cases of Italian companies per month
For the first three points I don't have no problems, and I have made this query:
SELECT FROM_UNIXTIME(time, '%Y-%M') as 'Month',
COUNT(CASE WHEN client = 'yes' THEN 1 ELSE NULL END) as 'Reports of a customer,
COUNT(CASE WHEN managed = 'yes' THEN 1 ELSE NULL END) as 'Managed cases',
COUNT(id) as 'Total reports'
FROM case
GROUP BY FROM_UNIXTIME(time, '%Y-%M')
ORDER BY FROM_UNIXTIME(time, '%Y-%m')
But how do I extract the monthly number of cases managed of any Italian company?
I tried to add this portion of query but does not go...
COUNT(CASE WHEN case.company = language.company AND language.lang = 'IT' THEN 1 ELSE NULL END) as 'Italian Case',
Can you help me? Thank you
Your thought was right, just needed to join the additional table:
SELECT FROM_UNIXTIME(t.time, '%Y-%M') as 'Month',
COUNT(CASE WHEN t.client = 'yes' THEN 1 END) as 'Reports of a customer',
COUNT(CASE WHEN t.managed = 'yes' THEN 1 END) as 'Managed cases',
COUNT(t.id) as 'Total reports',
COUNT(CASE WHEN language.lang = 'IT' THEN 1 END) as 'Italian Case',
FROM case t
JOIN language ON language.company = t.company
GROUP BY FROM_UNIXTIME(t.time, '%Y-%M')
ORDER BY FROM_UNIXTIME(t.time, '%Y-%m')
Please note that I removed ELSE NULL from your cases as it is the default.
Related
I have a table within a database, and I want to aggregate the questions and answers within them into a more readable data table. The source table 👇
+-----+----------------+----------------------------+----------------+
| QID | Date Submitted | Question | Answer |
+-----+----------------+----------------------------+----------------+
| 0 | 08/04/2021 | companyName | Yaneev |
| 1 | 08/04/2021 | humanRightPolicy | George Micheal |
| 2 | 08/04/2021 | accountManagerMobileNumber | 7474236843 |
| 3 | 08/04/2021 | swiftCode | AOEU326 |
| 4 | 03/04/2021 | companyName | Eimbee |
| 5 | 03/04/2021 | humanRightPolicy | Revvie George |
| 6 | 03/04/2021 | accountManagerMobileNumber | 7475123843 |
| 7 | 03/04/2021 | swiftCode | AOEU324 |
| 8 | 04/04/2021 | companyName | Yaneev |
| 9 | 04/04/2021 | humanRightPolicy | Mark Fox |
| 10 | 04/04/2021 | accountManagerMobileNumber | 74742121231 |
| 11 | 04/04/2021 | swiftCode | 124eoKK |
+-----+----------------+----------------------------+----------------+
And what I want the 'destination' table to look like 👇
+--------------+-------------------+----------------------------+-----------+
| Company Name | humanRightsPolicy | accountManagerMobileNumber | swiftCode |
+--------------+-------------------+----------------------------+-----------+
| Yaneev | George Micheal | 7474236843 | AOEU326 |
| Eimbee | Revvie George | 7475123843 | AOEU324 |
+--------------+-------------------+----------------------------+-----------+
I'd also like to know what kind of operation this is, as I feel that it's something that isn't new in any way.
SQL table represent unordered sets. Let me assume that you have an ordering column. With such a column, you can assign a group to each set of rows for the same company and then use conditional aggregation:
select max(case when question = 'Company Name' then answer end) as company_name,
max(case when question = 'Q1' then answer end) as q1,
max(case when question = 'Q2' then answer end) as q2,
max(case when question = 'Q3' then answer end) as q3
from (select t.*,
sum(case when question = 'Company Name' then 1 else 0 end) over (order by <ordering col>) as grp
from t
) t
group by grp;
Note that this answers the question that you asked, where all the questions are known -- so the result columns are all known. If you don't know the questions in advance, you need to use dynamic SQL (i.e. construct the query as a string and then execute it). How to do that depends entirely on the database you are using.
EDIT:
In older versions of MySQL, you can use a subquery:
select max(case when question = 'Company Name' then answer end) as company_name,
max(case when question = 'Q1' then answer end) as q1,
max(case when question = 'Q2' then answer end) as q2,
max(case when question = 'Q3' then answer end) as q3
from (select t.*,
(select count(*)
from t t2
where t2.question = 'Company Name' and
t2.<ordering col> <= t.<ordering col>
) as grp
from t
) t
group by grp;
I have 3 tables like the following.
Table "mansioni":
id_mansione | desc_mansione
1 | production
2 | office
3 | transport
Table "dipendente": store id, name and surname:
id_dip | nome_dip | cognome_dip
1 | piero | rossi
2 | marco | rossi
Table dipendenti_iddip: store the association between "dipendente" and table "mansioni"
iddip_mansione | num_mansione | id_mansione
1 | 1 | 1
1 | 2 | 2
2 | 1 | 2
2 | 2 | 3
Now I need a query that give me a result like this:
id_dip | nome_dip | cognome_dip | mansione1 | mansione2 | mansione3
1 | piero | rossi | production| office |
2 | marco | rossi | office | transport |
I arrived to the following query but with this I can only see the "id_mansione" and not the "desc mansione" field
select i.id_dip,
i.nome_dip,
i.cognome_dip,
max(case when t.num_mansione='1' then t.id_mansione end) Mansione1,
max(case when t.num_mansione='2' then t.id_mansione end) Mansione2,
max(case when t.num_mansione='3' then t.id_mansione end) Mansione3
from dipendente i
left join dipendenti_iddip t
on i.id_dip = t.iddip_mansione
group by i.id_dip, i.nome_dip, i.cognome_dip
How can I arrive to my result?
Thanks...
Add join on mansioni and replace t.id_mansione with m.desc_mansione
select i.id_dip,
i.nome_dip,
i.cognome_dip,
max(case when t.num_mansione = '1' then m.desc_mansione end) Mansione1,
max(case when t.num_mansione = '2' then m.desc_mansione end) Mansione2,
max(case when t.num_mansione = '3' then m.desc_mansione end) Mansione3
from dipendente i
join dipendenti_iddip t
on i.id_dip = t.iddip_mansione
join mansioni m on m.id_mansione = t.id_mansione
group by i.id_dip
I have following tables products and tests.
select id,pname from products;
+----+---------+
| id | pname |
+----+---------+
| 1 | prd1 |
| 2 | prd2 |
| 3 | prd3 |
| 4 | prd4 |
+----+---------+
select pname,testrunid,testresult,time from tests;
+--------+-----------+------------+-------------+
| pname | testrunid | testresult | time |
+--------+-----------+------------+-------------+
| prd1 | 800 | PASS | 2017-10-02 |
| prd1 | 801 | FAIL | 2017-10-16 |
| prd1 | 802 | PASS | 2017-10-02 |
| prd1 | 803 | NULL | 2017-10-16 |
| prd1 | 804 | PASS | 2017-10-16 |
| prd1 | 805 | PASS | 2017-10-16 |
| prd1 | 806 | PASS | 2017-10-16 |
+--------+-----------+------------+-------------+
I like to count test results for products and if there is no result available,for a product just show a zero for it. something like following table:
+--------+------------+-----------+----------------+---------------+
| pname | total_pass | total_fail| pass_lastweek | fail_lastweek |
+--------+------------+-----------+----------------+---------------+
| prd1 | 5 | 1 | 3 | 1 |
| prd2 | 0 | 0 | 0 | 0 |
| prd3 | 0 | 0 | 0 | 0 |
| prd4 | 0 | 0 | 0 | 0 |
+--------+------------+-----------+----------------++--------------+
I have tried different queries like following, which is just working for one product and is incomplete:
SELECT pname, count(*) as pass_lastweek FROM tests where testresult = 'PASS' AND time
>= '2017-10-11' and pname in (select pname from products) group by pname;
+-------------+---------------+
| pname | pass_lastweek |
+-------------+---------------+
| prd1 | 3 |
+-------------+---------------+
it looks so basic but still I am unable to write it, any idea?
Use conditional aggregation. The COUNT function count NULL values as zeros automatically, therefore, there is no need to take care of that.
select p.pname,
count(case when testresult = 'PASS' then 1 end) as total_pass,
count(case when testresult = 'FAIL' then 1 end) as total_fail,
count(case when testresult = 'PASS' and time >= curdate() - INTERVAL 6 DAY then 1 end) as pass_lastweek ,
count(case when testresult = 'FAIL' and time >= curdate() - INTERVAL 6 DAY then 1 end) as fail_lastweek ,
from products p
left join tests t on t.pname = p.pname
group p.id, p.pname
Generally, you need to LEFT JOIN the first table with the second one before you group. The join will give you a row for each product (even if there are no test results to join it to; INNER JOIN would exclude products with no associated tests) + an additional row for each test result (beyond the first). Then you can group them.
SELECT products.*, tests.* FROM products
LEFT JOIN tests ON products.pname = tests.pname
GROUP BY products.id
Also, I would strongly recommend using a product_id column in the tests table, rather than using pname (if a products.pname changes, your whole DB breaks unless you also update the pname field in kind for every test result). The general query would then look like this:
SELECT products.*, tests.* FROM products
LEFT JOIN tests ON products.id = tests.product_id
GROUP BY products.id
I used 2 queries , the first with conditional count and the second one is to change all null values into 0 :
select pname,
case when total_pass is null then 0 else total_pass end as total_pass,
case when total_fail is null then 0 else total_fail end as total_fail,
case when pass_lastweek is null then 0 else pass_lastweek end as pass_lastweek,
case when fail_lastweek is null then 0 else fail_lastweek end asfail_lastweek from (
select products.pname,
count(case when testresult = 'PASS' then 1 end) as total_pass,
count(case when testresult = 'FAIL' then 1 end) as total_fail,
count(case when testresult = 'PASS' and time >= current_date -7 DAY then 1 end) as pass_lastweek ,
count(case when testresult = 'FAIL' and time >= current_date -7 DAY then 1 end) as fail_lastweek ,
from products
left join tests on tests.pname = products.pname
group 1 ) t1
I have a table with three columns:
1. store name
2. data type (sales, return)
3. qty
---------------------------
| Stores | Data | Qty |
---------------------------
| HM | Sales | 15 |
| RD | Sales | 10 |
| HM | Return | 4 |
| RD | Return | 2 |
I want to select all store names, sales qty, return qty as following
--------------------------
| Store | Sales | Return |
--------------------------
| HM | 15 | 4 |
| RD | 10 | 2 |
Here's what I've tried:
SELECT store,
CASE `data`
WHEN 'Sales' THEN SUM(qty)
ELSE NULL
END as `Sales`,
CASE `data`
WHEN 'Return' THEN SUM(qty)
ELSE NULL
END as `Return`
FROM `full_report`
GROUP BY store
Result: I get wrong sales qty and Null for return qty!
You can use conditional aggregation . . . mixing case with sum():
select fr.store,
SUM(case when fr.data = 'Sales' then fr.qty else 0 end) as Sales,
SUM(case when fr.data = 'Return' then fr.qty else 0 end) as Returns
from full_report fr
group by fr.store;
The goal
Don't return the lowest price whose its markets are suspended.
The problem
I don't know the syntax.
The scenario
There is the following stored procedure to get the lowest and the biggest price of a specific product:
BEGIN
Select Min(Case When product.PromotionalPrice = 0
Then product.OriginalPrice Else
Least(product.PromotionalPrice, product.OriginalPrice)
End) As minProductPrice,
Max(Case When product.PromotionalPrice = 0
Then product.OriginalPrice Else
Least(product.PromotionalPrice, product.OriginalPrice)
End) As maxProductPrice
From products As product
Where product.Name = 'Playstation 3';
END
The context is: there are markets and products. Products belong to markets. If some market is suspended, then doesn't display its products and nor add them to max/min price comparison.
Can you all understand? I want to exclude the products whose its markets are suspended from the Min or Max statement of above's query.
The tables
Here is the markets table:
+----+------+-------------+
| Id | Name | SituationId |
+----+------+-------------+
| 1 | A | 1 |
+----+------+-------------+
| 2 | B | 2 |
+----+------+-------------+
| 3 | C | 3 |
+----+------+-------------+
Here is the markets_situations table:
+----+-----------+
| Id | Name |
+----+-----------+
| 1 | Neutral |
+----+-----------+
| 2 | Premium |
+----+-----------+
| 3 | Suspended |
+----+-----------+
And finally, here is the products table:
+----+---------------+--------+------------------+---------------+
| Id | Name | Market | PromotionalPrice | OriginalPrice |
+----+---------------+--------+------------------+---------------+
| 1 | Xbox 360 | 1 | 0 | 225,00 |
+----+---------------+--------+------------------+---------------+
| 2 | Xbox 360 | 2 | 99,00 | 175,00 |
+----+---------------+--------+------------------+---------------+
| 3 | Xbox 360 | 3 | 0 | 135,00 |
+----+---------------+--------+------------------+---------------+
| 4 | Playstation 3 | 1 | 0 | 189,00 |
+----+---------------+--------+------------------+---------------+
| 5 | Playstation 3 | 2 | 125,00 | 165,00 |
+----+---------------+--------+------------------+---------------+
| 6 | Playstation 3 | 3 | 110,00 | 185,00 |
+----+---------------+--------+------------------+---------------+
To enhance the comprehension
I don't want to display 110,00 as the Min price of the stored procedure's result because its market (C) is Suspended.
What I already did
I already tried the following, but without success:
BEGIN
[...]
Where product.Name = 'Playstation 3'
And marketSituation.Id <> 3;
END
What happens? The And condition does nothing. The query keeps returning me the price of the suspended market.
Select Min(Case When product.PromotionalPrice = 0
Then product.OriginalPrice Else
Least(product.PromotionalPrice, product.OriginalPrice)
End) As minProductPrice,
Max(Case When product.PromotionalPrice = 0
Then product.OriginalPrice Else
Least(product.PromotionalPrice, product.OriginalPrice)
End) As maxProductPrice
From products As product
Inner join markets on product.market = markets.id AND markets.SituationId <> 3
Where product.Name = 'Playstation 3';
How about something like
Select Min(Case When product.PromotionalPrice = 0
Then product.OriginalPrice Else
Least(product.PromotionalPrice, product.OriginalPrice)
End) As minProductPrice,
Max(Case When product.PromotionalPrice = 0
Then product.OriginalPrice Else
Least(product.PromotionalPrice, product.OriginalPrice)
End) As maxProductPrice
From products As product INNER JOIN
Markets ON Product.Market = Markets.Id
Where product.Name = 'Playstation 3'
AND Markets.SituationID <> 3