problem with two My SQL queries - mysql

I have table prod with structure
Id, name, keyword, yearborn.
It is necessary to bring the number of keywords grouped encountered in the field yearborn , for example
SELECT yearborn, COUNT(Id) cnt1 FROM prod WHERE keyword='admiral'
GROUP BY yearborn
and
SELECT yearborn, COUNT(Id) cnt2 FROM prod WHERE keyword='captain' GROUP BY yearborn
How do I combine these two queries to get the output result table with the structure
yearborn, cnt1, cnt2?
I have tried UNION
SELECT yearborn, COUNT(Id) cnt1 FROM prod WHERE keyword='admiral' GROUP BY yearborn
UNION
SELECT yearborn, COUNT(Id) cnt2 FROM prod WHERE keyword='captain' GROUP BY yearborn
But result is:
yearborn, cnt1
Tell me please how to get out of this situation.

SELECT yearborn,
SUM(IF(keyword = 'admiral', 1, 0)) cnt1,
SUM(IF(keyword = 'captain', 1, 0)) cnt2
FROM prod
WHERE keyword = 'admiral'
OR keyword = 'captain'
GROUP BY yearborn
The result will be something like this (of course this is fictitious data):
+----------+------+------+
| yearborn | cnt1 | cnt2 |
+----------+------+------+
| 2004 | 1233 | 0 |
| 1999 | 0 | 15 |
+----------+------+------+

You can use a SUM() on your keyword conditions to do this, because the result of comparisons in MySQL can be treated as 0 (false) or 1 (true):
SELECT yearborn, SUM(keyword='admiral') cnt1, SUM(keyword='captain') cnt2 FROM prod GROUP BY yearborn
This also has the advantage of only using one table scan (it's faster than using unions and subqueries).

SELECT yearborn, COUNT(Id) cnt1, NULL cnt2 FROM prod WHERE keyword='admiral' GROUP BY yearborn
UNION
SELECT yearborn, NULL cnt1, COUNT(Id) cnt2 FROM prod WHERE keyword='captain' GROUP BY yearborn

How about:
SELECT yearborn,SUM(cnt1),SUM(cnt2) FROM
(
SELECT yearborn, COUNT(id) cnt1, 0 cnt2 FROM prod WHERE keyword='admiral'
UNION ALL
SELECT yearborn, 0 cnt1, COUNT(id) cnt2 FROM prod WHERE keyword='captain'
)
GROUP BY yearborn

Well, you can try this:
SELECT `yearborn`,
COUNT(`Id`) AS `cnt1`
FROM `prod`
WHERE `keyword` IN ('admiral','captain')
GROUP BY `yearborn`,`keyword`;
edit:
added the keyword in GROUP BY statment.

Related

2 SELECT in a query with ORDER BY

I need to create a MYSQL query that will return the following:
excel
this is my query
SELECT t1.fecha_salida,
t1.agencia,
t2.fecha_salida,
t2.directa
FROM (SELECT fecha_salida, COUNT(*) AS agencia
FROM ventas
WHERE ventas.eliminado = 0 AND ventas.cliente_id !=2
GROUP BY fecha_salida) AS t1,
(SELECT fecha_salida, COUNT(*) AS directa
FROM ventas
WHERE ventas.eliminado = 0 AND ventas.cliente_id =2
GROUP BY fecha_salida) AS t2
GROUP BY t1.fecha_salida
my table is:
|------ |Columna|Tipo|Nulo|Predeterminado |------
|//**venta_id**//|int(11)|No| |usuario_id|int(11)|No|
|tour_id|int(11)|No| |cliente_id|int(11)|No| |vehiculo_id|int(11)|No|
|cashflow_id|int(11)|No| |total_compra|int(6)|No|
|total_pagado|int(6)|No| |total_iva|int(6)|No|
|total_comision|int(11)|No| |a_pagar|int(11)|No|
|fecha_venta|datetime|No| |fecha_salida|date|No|
|concretada|tinyint(1)|No| |pasajeros|int(3)|No|
|nombre|varchar(500)|Sí|NULL |direccion|varchar(500)|Sí|NULL
|observaciones|varchar(500)|Sí|NULL |forma_pago|tinyint(2)|No|
|eliminado|tinyint(1)|No|
Can you help me
You can use UNION to combine two queries that have same structure , also you should select from combined result and then order them
SELECT * FROM (
SELECT fecha_salida, COUNT(*) AS agencia
FROM ventas
WHERE `fecha_venta` between '2012-03-11 00:00:00' and '2019-08-30 23:59:00'
and ventas.eliminado = 0
AND ventas.cliente_id = 2
GROUP BY fecha_salida
UNION
SELECT fecha_salida, COUNT(*) AS agencia
FROM ventas
WHERE `fecha_venta` between '2012-03-11 00:00:00' and '2019-08-30 23:59:00'
and ventas.eliminado = 0
AND ventas.cliente_id != 2
GROUP BY fecha_salida
) RESULT
ORDER BY agencia

SQL max value form count()

I've got a following query:
SELECT BusID, count(BusID) as 'NoofConnections'
FROM mytable
Group By BusID
Order by BusID
And I get following table:
BusID NoofConnections
=========================
1 6
2 6
4 3
5 2
3 1
And I will to select just maximum from NoofConnections, so in this case LIMIT 1 doesn't work, so we have two equal values. Like this:
BusID NoofConnections
=========================
1 6
2 6
Any ideeas?
You can use a subquery:
SELECT BusID, COUNT(*) as NoofConnections
FROM mytable
GROUP BY BusID
HAVING COUNT(*) = (SELECT COUNT(*)
FROM mytable
GROUP BY BusID
ORDER BY COUNT(*) DESC
LIMIT 1
)
ORDER BY BusID;
You could use a subselect
select * from (
SELECT BusID, count(BusID) as NoofConnections
FROM mytable
Group By BusID
) t1
where t1.NoofConnections = ( select max(NoofConnections)
from (
SELECT BusID, count(BusID) as NoofConnections
FROM mytable
Group By BusID
)

Multiple select with single Group By query

I have these 3 fields in the table.
trans_date | transaction_type | client_id
What I need is a count of entries by transaction_types for each date. For example,
Date : 07/07/2015 total count : 6 transaction_type 1 count : 3 ,
transaction_type 2 count : 1, transaction_type 3 count : 2 etc....
And I need this for all the dates grouped by each date.
Here's my current query,
SELECT count(id) as total_count,
(select count(id) where transaction_type=1) as type1_count,
(select count(id) where transaction_type=2) as type2_count,
(select count(id) where transaction_type=3) as type3_count
FROM tblTransactions
where client_id=1
GROUP BY date(trans_date/1000, 'unixepoch')
This returns weird numbers that doesn't match. What am I doing wrong?
The reason that you are getting weird values is that your sub queries are not filtered by date so you will get the total count for each transaction type. What you need is a correlated subquery that will get a paremeter from outer query:
SELECT count(id) as total_count,
(select count(id) where transaction_type=1 and trans_date=t.trans_date) as type1_count,
(select count(id) where transaction_type=2 and trans_date=t.trans_date) as type2_count,
(select count(id) where transaction_type=3 and trans_date=t.trans_date) as type3_count
FROM tblTransactions t
where client_id=1
GROUP BY date(trans_date/1000, 'unixepoch')
You can use sum function instead of subqueries
select date(trans_date/1000, 'unixepoch') d,
sum(case when transaction_type = 1 then 1 else 0 end) type1_count,
sum(case when transaction_type = 2 then 1 else 0 end) type2_count,
sum(case when transaction_type = 3 then 1 else 0 end) type3_count
from tblTransactions
where client_id=1
group by d

Using multiple group by having in single query

I have 2 queries to get the count of families having count = 1 and count = 2.
SELECT Name, count(*) as c FROM Tablename GROUP BY HOUSE_NO HAVING c<=1;
SELECT Name, count(*) as c FROM Tablename GROUP BY HOUSE_NO HAVING c>=2 and c<=4;
But i need to combine those queries into single query.Like
count1 count2
nooffamiliesHavingcount = 1 nooffamiliesHavingcount = 2
Please help me....Thanks in advance..
You need to put your first count into a subquery:
SELECT COUNT(CASE WHEN C = 1 THEN 1 END) AS nooffamiliesHavingcount1,
COUNT(CASE WHEN C = 2 THEN 1 END) AS nooffamiliesHavingcount2
FROM ( SELECT COUNT(*) AS C
FROM TableName
GROUP BY House_No
) t
WHERE c IN (1, 2);
EDIT
If you need to do ranges in your count you can use this:
SELECT COUNT(CASE WHEN C <= 1 THEN 1 END) AS nooffamiliesHavingcount1,
COUNT(CASE WHEN C BETWEEN 2 AND 4 THEN 1 END) AS nooffamiliesHavingcount2,
COUNT(CASE WHEN C > 4 THEN 1 END) AS nooffamiliesHavingcount3
FROM ( SELECT COUNT(*) AS C
FROM TableName
GROUP BY House_No
) t
Example on SQL Fiddle
SELECT CASE WHEN c <= 1 THEN "<=1"
WHEN c BETWEEN 2 and 4 THEN "2-4"
END familysize,
COUNT(*) nooffamilies
FROM (SELECT Name, count(*) c
FROM Tablename
GROUP BY Name) x
GROUP BY familysize
HAVING familysize IS NOT NULL
FIDDLE

MYSQL GROUP BY multiple derived tables?

I have this query which does some calculations based on some derived tables that are linked with an INNER JOIN.
At the moment I have a WHERE clause which pulls out one id at a time. But how can I make it list all the ids?
I have tried GROUP BY in various places but can't figure it out.
My query so far is as follows:
SELECT
equipment_id,
service_duration,
available_duration,
(available_duration / service_duration)*100 AS availability
FROM (
SELECT
SUM(service_end_time - service_start_time) AS service_duration
FROM(
SELECT equipment_id,
(CASE
END) AS service_start_time,
(CASE
END) AS service_end_time
FROM t1
WHERE equipment_id = 'EX123'
)AS A
) AS B
JOIN(
SELECT equipment_id,
SUM(available_end_time - available_start_time) AS available_duration
FROM (
SELECT equipment_id,
(CASE
END) AS available_start_time,
(CASE
END) AS available_end_time
FROM t2
WHERE equipment_id = 'EX123'
) AS C
) AS D
ON equipment_id=D.equipment_id
What I want to do is replace the WHERE clause with a GROUP BY to list all the ids, or similar, but getting that to work is beyond my skill level... Any help greatly appreciated :)
Try below:
SELECT
equipment_id, service_duration, available_duration,
(available_duration / service_duration)*100 AS availability
FROM
(
SELECT equipment_id,
SUM(service_end_time - service_start_time) AS service_duration
FROM
(
SELECT equipment_id,
(CASE ... END) AS service_start_time,
(CASE ... END) AS service_end_time
FROM t1
) AS A
GROUP BY equipment_id
) AS B
JOIN
(
SELECT equipment_id,
SUM(available_end_time - available_start_time) AS available_duration
FROM
(
SELECT equipment_id,
(CASE ... END) AS available_start_time,
(CASE ... END) AS available_end_time
FROM t2
) AS C
GROUP BY equipment_id
) AS D
ON equipment_id=D.equipment_id
Try this (replace my field names with your field names):
SELECT
a.emp_id,
service_duration,
available_duration
FROM
(
SELECT
emp_id,
SUM(service_end_time - service_start_time) AS service_duration
FROM
data
GROUP BY
emp_id
) a
JOIN
(
SELECT
emp_id,
SUM(available_end_time - available_start_time) AS available_duration
FROM
data
GROUP BY
emp_id
) b
ON a.emp_id = b.emp_id
GROUP BY
a.emp_id