mysql: grouping fields in one table separately - mysql

I need to get the averages for the following kind of data out of MySQL:
There is one table:
table 1
field_a, field_b, field_c
data_a , data_a , data_c
data_a , data_b , data_c
data_a , data_a , data_c
what I need to output is (this part does not need to be in mysql, just explaining the data I need) :
100% of field_a is data_a
33% of field_b is data_b and 66% is data_a
100% of field_c is data_c
I tried grouping by each field but it did not give the desired results. What would be the best way to approach this? (currently I've just set it up to run separate queries for each field but there are quite a few so I would like them in one big query/something a little more efficient).
also, apologies for the title. I couldn't really think of a better way to explain it. Feel free to edit with something more succinct.

I can only think of UNION use:
(SELECT field_a AS val, COUNT(field_a) AS cnt, 'A' AS fld_name
FROM table1 GROUP BY field_a)
UNION
(SELECT field_b AS val, COUNT(field_b) AS cnt, 'B' AS fld_name
FROM table1 GROUP BY field_b)
UNION
(SELECT field_c AS val, COUNT(field_c) AS cnt, 'C' AS fld_name
FROM table1 GROUP BY field_c)
It will give us the record set containing in each row:
Field value,
Number of such values in table,
Field name.

select 'field a', fa, cfa * 100.0 / total
from (
select
fa, count(fa) as cfa
from t
group by fa
) t
inner join (
select count(*) as total
from t
) s on 1 = 1
union
select 'field b', fb, cfb * 100.0 / total
from (
select
fb, count(fb) as cfb
from t
group by fb
) t
inner join (
select count(*) as total
from t
) s on 1 = 1
union
...
If you are looking for a dynamically built query it can be done but this is not it.

Related

To find the max(sum) in MYSQL for a particular id in 2 different columns

I have a table which looks like
I need the sum of goal of a particular team_id
for example :
If team_id 16 has scored goal 6 and 2 respectively the sum would be 8 in another new column sum_goal
I am unable to proceed further. Kindly help.
the query which i had tried is :
Select ( match_id, Sum(Goal) From
(
Select team1_id ID, team1_goal Goal From match_result_updation
Union All
Select team2_id ID, team2_goal Goal From match_result_updation
)
as A)
FROM
(SELECT
c.tournament_id , g.*
FROM team_trophies d
INNER JOIN
tournament_match e
ON
e.tournament_id = d.tournament_id
INNER JOIN
tournament_scheduling c
ON
c.tournament_id = e.tournament_id
INNER JOIN
matches f
on
f.match_id = c.id
INNER JOIN
match_result_updation g
ON
g.match_id = f.id
WHERE
f.match_type = 'tournament'
and
d.tournament_id = 1) as p
Group By match_id
From the second select to id = 1 i am getting the output as in the attachment picture but I am unable to find the sum for goals each team_id.
also if teamid 16 or 17 either team1 or team2 accordingly sum of the goals will be calculated.
My first thought would be to put them in like columns and then sum.
EDIT Any SQL Engine
Select ID, Sum(Goal) From
(
Select Team1_ID ID, Team1_Goal Goal From Table
Union All
Select Team2_ID ID, Team2_Goal Goal From Table
) A
Group By ID
ps This kind of workaround would not be necessary if the table design were normalized.
Use this query it will help to sum of goal
select team1_id, sum(team1_goal) as sum_goal from `table` group by `team1_id`;
We can do like this also....
select team1_id, sum(team1_goal) as sum_goal from `table` group by `team1_id`
union all
select team2_id, sum(team2_goal) as sum_goal from `table` group by `team1_id`;
If you want to sum again then can use like this
select t.team_id, sum(t.sum_goal) as total_goal from (
select team1_id as team_id, sum(team1_goal) as sum_goal from `table` group by `team1_id`
union all
select team2_id as team_id, sum(team2_goal) as sum_goal from `table` group by `team1_id`
) as t group by t.team_id;
try this
Select ID, Sum(Goal) From
(
Select Team1_ID ID, Team1_Goal Goal From Table
Union All
Select Team2_ID ID, Team2_Goal Goal From Table
)l,
table_name Group By ID
Another version:
SELECT SUM(nr)
FROM (
(SELECT sum(team1_goal) as nr FROM goals WHERE team1_id = 16)
UNION ALL
(SELECT sum(team2_goal) as nr FROM goals WHERE team2_id = 16)
)
sum
SELECT team1_id AS Team_ID , sum(team1_goal) as Team_Goal
FROM
teams GROUP BY team1_id
UNION
SELECT team2_id AS Team_ID , sum(team2_goal) as Team_Goal
FROM teams GROUP BY team2_id
This will create one table with the ID of each team and the total number of goals made by each team ID

Mysql Join query with count table records with same date

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.

MySQL - COUNT scatter classified by multiple records

I have SQL table:
CREATE TABLE `test_results` (
`id` int AUTO_INCREMENT,
`date_time` datetime,
`altpn` varchar(60),
`vsp` decimal(10,4),
PRIMARY KEY (`id`)
);
VALUES
(null, 2016-07-22 13:30:01, pn1, 14.55),
(null, 2016-07-22 13:30:02, pn1, 14.45),
(null, 2016-07-22 13:30:03, pn1, 14.55),
(null, 2016-07-22 13:30:04, pn2, 14.45),
(null, 2016-07-22 13:30:05, pn2, 14.65),
(null, 2016-07-22 13:30:06, pn2, 14.45);
And i need result like this:
vsp - altpn - COUNT
14.45 - pn1 - 1
14.45 - pn2 - 2
14.55 - pn1 - 2
14.55 - pn2 - 0
14.65 - pn1 - 0
14.65 - pn2 - 1
It can also be altpn - vsp - COUNT, it does not matter. But every vsp value must contain all pns, which are in table. Even that with zero value.
Is this even possible to do? I can do normal SQL like:
SELECT test_results.vsp,
test_results.altpn,
COUNT(*)
FROM test_results
GROUP BY test_results.vsp,
test_results.altpn
and re-compute this result in php to table what i need (For chart), but it will by easier do it in SQL.
SELECT d.*,
c.*,
(SELECT count(*)
FROM test_results e
WHERE e.altpn=d.idaltpn
AND e.vsp=c.idvsp)
FROM
(SELECT distinct(a.altpn) idaltpn
FROM test_results a) d,
(SELECT distinct(a.vsp) idvsp
FROM test_results a) c
You are close. You'll want to assemble together a list of all the unique vsp/altpn and then left join that to a count subquery. I'm going to use a crossjoin of distinct values of vps to the distinct values of altpn to create that list for you...you might want to use business logic if there is something that determines when a vsp/altpn combination is valid in your results.
select a.vsp, a.altpn, ifnull(counts.totalcount,0)
from (select vsp.vsp, altpn.altpn
from (select vsp
from test_results
group by vsp)vsp
join
(select altpn
from test_results
group by altpn)altpn
on 1=1) a
left join
(SELECT test_results.vsp, test_results.altpn, COUNT(*) as totalcount
FROM test_results
GROUP BY test_results.vsp, test_results.altpn) counts
on a.vsp = counts.vsp and a.altpn = counts.altpn

union all two table but diff number of column

select count(*) as total FROM ( SELECT * FROM database1.orders WHERE number LIKE "11111111111111111" UNION ALL SELECT * FROM database2.orders WHERE number LIKE "11111111111111111" ) AS b
but i got error :
The used SELECT statements have a different number of columns
because run SELECT * FROM database2.orders WHERE number LIKE "11111111111111111" give me a result is null.
How to merge it with a query because with a query to help me process the pagination
Thank for helps !
Just do the aggregation before the union all:
select sum(cnt) as total
FROM ((SELECT count(*) as cnt
FROM database1.orders
WHERE number LIKE '11111111111111111'
)
UNION ALL
(SELECT count(*) as cnt
FROM database2.orders
WHERE number LIKE '11111111111111111'
)
) t;
Note I changed the string delimiter to be a single quote rather than a double quote. It is good practice to use single quotes for string and date constants (and nothing else).
By the way, you can also do this using a join:
select o1.cnt1, o2.cnt1, (o1.cnt1 + o2.cnt1) as total
FROM (SELECT count(*) as cnt1
FROM database1.orders
WHERE number LIKE '11111111111111111'
) o1 cross join
(SELECT count(*) as cnt2
FROM database2.orders
WHERE number LIKE '11111111111111111'
) o2;
This makes it easier to get the individual counts for the two databases.
The orders table in database1 probably has a different number of columns than the table by the same name in database2.
Instead of using select *, select the columns you're interested in, like select userid, productid, deliveryaddress, .... Make sure you specify the same columns in both parts of the union.
For a count(*), you could choose no columns at all, and select the value 1 for each row, like:
select count(*)
from (
select 1
from database1.orders
where number like '111'
union all
select 1
from database2.orders
where number like '111'
) as SubQueryAlias
Or you can add the result of two subqueries without a union:
select (
select count(*)
from database1.orders
where number like '111'
)
+
(
select count(*)
from database2.orders
where number like '111'
)

How to find the mode of a set of data before joining with another table?

These are the two tables I am looking at:
k3_alert_types
Type Description
0 No Show
1 Stop Arrival
2 ...
3 ...
4 ...
5 ...
k3_alert
Type
1
22
33
2
4
5
65
33
1
The tables are just examples, as the actual data sets are much larger. What I would like to do is find the mode of types in the k3_alert table, which I have done with the following:
SELECT TYPE , number_of_alerts
FROM
(
SELECT id, TYPE, COUNT(TYPE) AS number_of_alerts FROM k3_alert
GROUP BY TYPE
)t1
WHERE number_of_alerts IN
(
SELECT MAX( count_type ) FROM
(
SELECT id, TYPE , COUNT(TYPE ) AS count_type FROM k3_alert
GROUP BY TYPE
)t
)
I know how to join both tables:
SELECT k3_alert_types.description, k3_alert_types.type as type
FROM k3_alert_types
INNER JOIN k3_alert ON k3_alert_types.type = k3_alert.type
ORDER BY type
But I don't know how to do both at once.
I want to see this as the outcome of the whole process (just an example):
Description Type number_of_alerts
No Show 1 350
Any suggestions?
edit: Server type: MariaDB,
PHP extension: mysql
This should work:
SELECT at.description, at.type, COUNT(*) as number_of_alerts
FROM k3_alert_types at
INNER JOIN k3_alert a ON at.type = a.type
GROUP BY at.description, at.type
ORDER BY number_of_alerts DESC
LIMIT 1
So what I did was I used a CTE to store the value of mode and then selected top 1. If you wanted more flexibility or have a huge dataset you can use a temp table instead of a CTE.
Below is the code:
DECLARE #AlertType TABLE
(Type1 INT,
Descr varchar(20))
INSERT INTO #AlertType
(
Type1,
Descr
)
VALUES
( 1, 'Stop Arrival'),( 0,'No Show')
DECLARE #Alert TABLE
(Type1 INT)
INSERT INTO #Alert
(
Type1
)
VALUES (1),(0),(1),(23),(1),(5),(1)
;WITH CTE AS
(SELECT Type1, COUNT(*) AS number_of_alerts
FROM #Alert
GROUP BY Type1
)
SELECT TOP 1 AT.Descr, t1.Type1, t1.number_of_alerts
FROM CTE AS t1
JOIN #AlertType AS AT
ON AT.Type1 = t1.Type1
ORDER BY t1.number_of_alerts DESC