sum column counts for two different values - mysql

i have a column that can hold 6 values (1,2,3,A,B,C)
i can count(*) them so it looks like this
select mycol, count(*) as ttl from mytable group by mycol;
mycol ttl
1 46
2 53
3 10
A 5
B 4
C 2
but i want to sum the 1s and the As, and the 2s and the Bs like this
mycol total
var1 51
var2 57
var3 12
will a case statement work for this? like case 1 or A then treat them the same

Yes, a case statement will work for this:
select (case when mycol in ('1', 'var1') then 'var1'
when mycol in ('2', 'var2') then 'var2'
when mycol in ('3', 'var3') then 'var3'
end),
sum(ttl) as Total
from mytable t
group by (case when mycol in ('1', 'var1') then 'var1'
when mycol in ('2', 'var2') then 'var2'
when mycol in ('3', 'var3') then 'var3'
end);
EDIT:
If you just have the data with multiple rows for each value:
select (case when mycol in ('1', 'var1') then 'var1'
when mycol in ('2', 'var2') then 'var2'
when mycol in ('3', 'var3') then 'var3'
end),
count(*) as Total
from mytable t
group by (case when mycol in ('1', 'var1') then 'var1'
when mycol in ('2', 'var2') then 'var2'
when mycol in ('3', 'var3') then 'var3'
end);

Related

Select highest value based on aggregate function - SQL

I have a GiftSales table, it contains the id of the item (giftId), and the category of that item (categoryId)
I need to get the best selling item for each category.
Right now my query looks like this
SELECT giftId, categoryId, COUNT(giftId) as Total
FROM GiftSales
GROUP BY giftId, categoryId
And its giving me
==================================
|| giftId || categoryId || Total||
==================================
|| 1 || 1 || 8 ||
==================================
|| 2 || 1 || 5 ||
==================================
|| 23 || 2 || 12 ||
==================================
I need to only show the highest value per each category, so basically, the table shouldn't contain the second item.
I'd recommend using a window function, and dense_rank can be helpful when looking at top selling products by category as you may want to include any ties.
Schema (MySQL v8.0)
CREATE TABLE IDs (
`gift_id` INTEGER,
`category_id` INTEGER
);
INSERT INTO IDs
(`gift_id`, `category_id`)
VALUES
('1', '1'),
('1', '1'),
('1', '1'),
('1', '1'),
('1', '1'),
('1', '1'),
('1', '1'),
('1', '1'),
('2', '1'),
('2', '1'),
('2', '1'),
('2', '1'),
('2', '1');
Query #1
select a.category_id,a.gift_id,a.total from (
select
category_id,
gift_id,
count(gift_id) as total,
dense_rank() over (partition by category_id order by count(gift_id) desc) as ranking
from IDs group by 1,2) as a where ranking = 1;
category_id
gift_id
total
1
1
8
View on DB Fiddle
Use a window function such as MAX OVER per category:
select giftid, categoryid, total
from
(
select
giftid,
categoryid,
count(*) as total,
max(count(*)) over (partition by categoryid) as category_max
from giftsales
group by giftid, categoryid
) aggregated
where total = category_max;
SELECT DISTINCT categoryId, MAX(Total) as total FROM(
SELECT giftId, categoryId, COUNT(giftId) as Total FROM GiftSales GROUP BY giftId, categoryId
) AS T GROUP BY giftId, categoryId;
I got it working by using the distinct with the categoryId and since you need the total by category I removed the giftId and everything worked fine :) I used a playground to test this and the playground can be found here -> https://www.db-fiddle.com/f/qsGLKUZyos2ZKTftykkazd/0

MySQL-Count consective number

Write a SQL query to find number position as well number and consective number count
CREATE TABLE Logs (
`Id` INTEGER,
`Num` INTEGER
);
INSERT INTO Logs
(`Id`, `Num`)
VALUES
('1', '1'),
('2', '1'),
('3', '1'),
('4', '2'),
('5', '1'),
('6', '2'),
('7', '2');
Prefere Return
StartId Num Count
1 1 3
4 2 1
5 1 1
6 2 2
and also can i get any suggestion which function can be use with case function in MySQL Function
Looking at your data and expected results, I believe your expectations are inconsistent, eg you can either have 1 and 6 or 3 and 7.
What you need to do is group the data by successive num values and aggregate the results.
with gp as (
select *,
Row_Number() over(order by id)
- Row_Number() over(partition by num order by id) g
from logs
)
select Min(id) Id,
num, Count(*) Count
from gp
group by g, num
order by id

Verify migrated records in SQL Server tables

I have a scenario where I transferred data from table t1 to t2. Not every record was transferred. I want to figure out which IDs were completely transferred. For example, I have a subset of data in which both IDs 23 and 25 has 5 records each with different section and subsections. Since only 2 records from ID 23 were transferred to t2, I do not want them in my resultant query. Whereas, for ID 25, all the records were transferred to t2. So, I want it to reflect in my result.
I got this far
select *
from t2
where exists (select * from t1
where t1.id = t2.id
and t1.section = t2.section
and t1.sub = t2.sub
group by id)
Table 1
id section sub
----------------
23 1 9
23 1 10
23 2 2
23 3 2
23 3 3
24 1 9
24 1 10
24 2 2
24 3 2
24 3 3
25 1 9
25 1 10
25 2 2
25 3 2
25 3 3
Table 2
id section sub
----------------
23 1 9
23 1 10
25 1 9
25 1 10
25 2 2
25 3 2
25 3 3
Required result:
id section sub
---------------
25 1 9
25 1 10
25 2 2
25 3 2
25 3 3
Code to create tables
CREATE TABLE t1
(
id varchar(3),
section varchar(4),
sub varchar(2)
)
CREATE TABLE t2
(
id varchar(3),
section varchar(4),
sub varchar(2)
)
INSERT INTO t1 (id, section, sub)
VALUES ('23', '1', '9')
INSERT INTO t1 (id, section, sub)
VALUES ('23', '1', '10')
INSERT INTO t1 (id, section, sub)
VALUES ('23', '2', '2')
INSERT INTO t1 (id, section, sub)
VALUES ('23', '3', '2')
INSERT INTO t1 (id, section, sub)
VALUES ('23', '3', '3')
INSERT INTO t1 (id, section, sub)
VALUES ('24', '1', '9')
INSERT INTO t1 (id, section, sub)
VALUES ('24', '1', '10')
INSERT INTO t1 (id, section, sub)
VALUES ('24', '2', '2')
INSERT INTO t1 (id, section, sub)
VALUES ('24', '3', '2')
INSERT INTO t1 (id, section, sub)
VALUES ('24', '3', '3')
INSERT INTO t1 (id, section, sub)
VALUES ('25', '1', '9')
INSERT INTO t1 (id, section, sub)
VALUES ('25', '1', '10')
INSERT INTO t1 (id, section, sub)
VALUES ('25', '2', '2')
INSERT INTO t1 (id, section, sub)
VALUES ('25', '3', '2')
INSERT INTO t1 (id, section, sub)
VALUES ('25', '3', '3')
INSERT INTO t2 (id, section, sub)
VALUES ('23', '1', '9')
INSERT INTO t2 (id, section, sub)
VALUES ('23', '1', '10')
INSERT INTO t2 (id, section, sub)
VALUES ('25', '1', '9')
INSERT INTO t2 (id, section, sub)
VALUES ('25', '1', '10')
INSERT INTO t2 (id, section, sub)
VALUES ('25', '2', '2')
INSERT INTO t2 (id, section, sub)
VALUES ('25', '3', '2')
INSERT INTO t2 (id, section, sub)
VALUES ('25', '3', '3')
You can try the following, just need to count the number of each ID in t2 and compare that to the same count in t1 where they are the same:
select id,section,sub from (
select *, Count(*) over(partition by id) c
from t2
)t
where c=(
select Count(*)
from t1
where t1.id=t.id
group by t1.id
)

MySQL: Count Columns Per Row

I just want to know if counting columns is possible as you're counting rows without calling each column name. For example:
SELECT COUNT(FOUND COLUMNS) AS counted FROM table WHERE a_value EXISTS IN COLUMNS
/*
The same as this specified one. This is working but I'm
looking for another approach without calling each column name.
SELECT (IF(col1="Y",1,0) + IF(col2="Y",1,0)) as counted FROM table
*/
Which I wish will throw results per row like:
| counted |
|-----------|
| 2 |
| 1 |
| 0 |
IS THAT POSSIBLE? If yes, how?
SELECT COUNT(COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_CATALOG = 'database' AND TABLE_SCHEMA = 'dbo'
AND TABLE_NAME = 'table'
Try this it will work.
I think you are looking for that
THE SCHEMA
CREATE TABLE `numbers`( `col1` INT, `col2` INT, `col3` INT, `col4` INT );
INSERT INTO `numbers` (`col1`, `col2`, `col3`, `col4`) VALUES ('0', '0', '0', '6');
INSERT INTO `numbers` (`col1`, `col2`, `col3`, `col4`) VALUES ('1', '0', '0', '9');
INSERT INTO `numbers` (`col1`, `col2`, `col3`, `col4`) VALUES ('4', '1', '0', '2');
INSERT INTO `numbers` (`col1`, `col2`, `col3`, `col4`) VALUES ('9', '5', '1', '3');
INSERT INTO `numbers` (`col1`, `col2`, `col3`, `col4`) VALUES ('5', '0', '6', '4');
INSERT INTO `numbers` (`col1`, `col2`, `col3`, `col4`) VALUES ('2', '0', '1', '6');
INSERT INTO `numbers` (`col1`, `col2`, `col3`, `col4`) VALUES ('8', '5', '6', '7');
COUNT THE VALUE '0' OF EACH ROW
SELECT (c1+c2+c3+c4) AS counted FROM
(
SELECT
CASE WHEN col1 = 0 THEN 1 ELSE 0 END AS c1,
CASE WHEN col2 = 0 THEN 1 ELSE 0 END AS c2,
CASE WHEN col3 = 0 THEN 1 ELSE 0 END AS c3,
CASE WHEN col4 = 0 THEN 1 ELSE 0 END AS c4
FROM numbers
) AS temp_count
/RESULT/
counted
3
2
1
0
1
1
0
COUNT THE VALUE '7' OF EACH ROW
SELECT (c1+c2+c3+c4) AS counted FROM
(
SELECT
CASE WHEN col1 = 7 THEN 1 ELSE 0 END AS c1,
CASE WHEN col2 = 7 THEN 1 ELSE 0 END AS c2,
CASE WHEN col3 = 7 THEN 1 ELSE 0 END AS c3,
CASE WHEN col4 = 7 THEN 1 ELSE 0 END AS c4
FROM numbers
) AS temp_count
So you must replace the value of col1 = 7,col2 = 7,col3 = 7,col4 = 7, if you want check the others value.

Mysql query to pull data in the form of matrix

I have data in database with three columns id, topic, and subtopic. Something like this,
CREATE TABLE Table2 (`id` int, `topic` varchar(5), `subtopic` varchar(6));
INSERT INTO Table2 (`id`, `topic`, `subtopic`) VALUES
(1, 'place', 'paris'),
(1, 'group', 'A'),
(1, 'group', 'B'),
(2, 'place', 'us'),
(2, 'group', 'C'),
(3, 'group', 'A'),
(3, 'water', 'salt'),
(4, 'water', 'sweet'),
(4, 'world', 'ep'),
(5, 'place', 'venus'),
(5, 'place', 'paris'),
(5, 'group', 'A');
I want to output the result matrix place vs group from topic. Something like this.
Paris|US|Venus
A 2 |0 | 1
B 1 |0 | 0
C 0 |1 | 0
Idea is to pick up all the values of 'Group' (A,B,C) and 'Places' (paris,us,venus) in subtopic column. And then find number of co-occurrences with such condition.
Any idea how to solve in MySql?
You will need to join on your table twice to get the group and places, then you can use an aggregate function with a CASE expression to convert the rows into columns:
select g.subtopic as `group`,
sum(case when p.subtopic = 'Paris' then 1 else 0 end) Paris,
sum(case when p.subtopic = 'US' then 1 else 0 end) US,
sum(case when p.subtopic = 'Venus' then 1 else 0 end) Venus
from table2 g
left join table2 p
on g.id = p.id
and p.topic = 'place'
where g.topic = 'group'
group by g.subtopic;
See SQL Fiddle with Demo.
If you are going to have unknown values for the subtopic, then you can use a prepared statement and dynamic SQL:
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'sum(case when p.subtopic = ''',
subtopic,
''' then 1 else 0 end) as `',
subtopic, '`')
) INTO #sql
FROM table2
where topic = 'place';
SET #sql = CONCAT('SELECT g.subtopic as `group`, ', #sql, '
from table2 g
left join table2 p
on g.id = p.id
and p.topic = ''place''
where g.topic = ''group''
group by g.subtopic');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
See SQL Fiddle with Demo