Can someone suggest me a query to get combined count from 2 columns. My specific requirement is as following:
A B Permission
--------------------------
1 2 accept
2 3 accept
3 4 accept
1 6 accept
1 4 accept
2 1 accept
3 1 accept
4 1 pending
I want the count of 1 whether it belong to A or B and the permission is 'accept'. For the above example I need the output as 5
You can do this by denormalizing first the data using UNION ALL and then use COUNT to achieve the desired result:
WITH SampleData(A, B, Permission) AS(
SELECT 1, 2, 'accept' UNION ALL
SELECT 2, 3, 'accept' UNION ALL
SELECT 3, 4, 'accept' UNION ALL
SELECT 1, 6, 'accept' UNION ALL
SELECT 1, 4, 'accept' UNION ALL
SELECT 2, 1, 'accept' UNION ALL
SELECT 3, 1, 'accept' UNION ALL
SELECT 4, 1, 'pending'
)
SELECT
t.ColValue,
ValueCount = COUNT(*)
FROM (
SELECT
Col = 'A', ColValue = A, Permission
FROM SampleData
UNION ALL
SELECT
Col = 'B', ColValue = B, Permission
FROM SampleData
) t
WHERE Permission = 'accept'
GROUP BY t.ColValue
RESULT
ColValue ValueCount
----------- -----------
1 5
2 3
3 3
4 2
6 1
SELECT COUNT(*) FROM table WHERE (A=1 OR B=1) AND Permission LIKE 'accept'
You mean this?
As you said A or B, I think when you have 1 in A And in B it means 1 count; So I suggest this edited query?
SELECT M, COUNT(*) As C
FROM (
SELECT A as M, Permission
FROM yourTable
UNION ALL
SELECT B, Permission
FROM yourTable
WHERE A <> B) Dt
WHERE Permission = 'accept'
GROUP BY M
I got the answer and changed it to work for postgre :
WITH SampleData(auid, buid, permission) AS(
SELECT 1, 2, 'accept' UNION ALL
SELECT 2, 3, 'accept' UNION ALL
SELECT 3, 4, 'accept' UNION ALL
SELECT 1, 6, 'accept' UNION ALL
SELECT 1, 4, 'accept' UNION ALL
SELECT 2, 1, 'accept' UNION ALL
SELECT 3, 1, 'accept' UNION ALL
SELECT 4, 1, 'pending')
SELECT t.col, COUNT(*)as count
FROM (
SELECT auid as col, permission FROM SampleData
UNION ALL
SELECT buid as col, permission FROM SampleData
) t
WHERE permission = 'accept'
GROUP BY t.col
Result
col count
----------- -----------
1 5
2 3
3 3
4 2
6 1
Related
Table: signin
username
class
aaa
1
aaa
1
bbb
1
bbb
1
ccc
1
ddd
2
ddd
2
eee
2
There are two classes. How do I get first TWO username who has the most total count for each class(class-1 & class-2) like below ↓.
username
class
total
aaa
1
2
bbb
1
2
ddd
2
2
eee
2
1
EDIT: Is there any way not using over partition by?
In older version of MySQL you need to generate the ranking manually without any ranking function. Below code will work.
Schema and insert statements:
create table signin(username varchar(50),class int);
insert into signin values('aaa', 1);
insert into signin values('aaa', 1);
insert into signin values('bbb', 1);
insert into signin values('bbb', 1);
insert into signin values('ccc', 1);
insert into signin values('ddd', 2);
insert into signin values('ddd', 2);
insert into signin values('eee', 2);
Query:
select username,class,total
from
(
select username,class,count(*) total ,
#rn := IF(#prev = class, #rn + 1, 1) AS rn,
#prev := class
from signin
JOIN (SELECT #prev := NULL, #rn := 0) AS vars
group by class,username
order by class,username,count(*) desc
)t
where rn<=2
Output:
username
class
total
aaa
1
2
bbb
1
2
ddd
2
2
eee
2
1
db<fiddle here
Rank them by count in descending order and display only the first two. Sample data in lines #1 - 10; query begins at line #11.
SQL> with signin (username, class) as
2 (select 'aaa', 1 from dual union all
3 select 'aaa', 1 from dual union all
4 select 'bbb', 1 from dual union all
5 select 'bbb', 1 from dual union all
6 select 'ccc', 1 from dual union all
7 select 'ddd', 2 from dual union all
8 select 'ddd', 2 from dual union all
9 select 'eee', 2 from dual
10 )
11 select username, class, total
12 from (select username, class, count(*) total,
13 rank() over (partition by class order by count(*) desc) rnk
14 from signin
15 group by username, class
16 )
17 where rnk <= 2
18 order by class, username;
USE CLASS TOTAL
--- ---------- ----------
aaa 1 2
bbb 1 2
ddd 2 2
eee 2 1
SQL>
With rank() ranking window function and common table expression you can easily achieve that.
To get the usernames with most count in a class I have used rank()over (partition by class order by count(*) desc) along with group by class,username
Schema and insert statements:
create table signin(username varchar(50),class int);
insert into signin values('aaa', 1);
insert into signin values('aaa', 1);
insert into signin values('bbb', 1);
insert into signin values('bbb', 1);
insert into signin values('ccc', 1);
insert into signin values('ddd', 2);
insert into signin values('ddd', 2);
insert into signin values('eee', 2);
Query:
with cte as
(
select username,class,count(*) total,
rank()over (partition by class order by count(*) desc) rn
from signin
group by class,username
)
select username,class,total from cte where rn<=2
Output:
username
class
total
aaa
1
2
bbb
1
2
ddd
2
2
eee
2
1
db<>fiddle here
In older versions of MySQL, you would use variables. But you have to be careful with the syntax.
The basic idea is aggregation and then enumeration:
select uc.*
from (select uc.*,
(#rn := if(#c = class, #rn + 1,
if(#c := class, 1, 1)
)
) as seqnum
from (select username, class, count(*) as cnt
from signin
group by username, class
order by class, cnt desc
) uc cross join
(select #c := '', #rn := 0) params
) uc
where seqnum <= 2;
There are three very important things to remember when using variables in a select:
They are deprecated. In more recent versions, you should be using window functions for this type of operation.
MySQL does not guarantee the order of evaluation of expressions in a SELECT. So, you should handle all variables in a single expression, which is why the #rn := is rather complicated.
MySQL does not guarantee that the ORDER BY is evaluated before the variable assignments. That is why the ORDER BY is in the subquery.
I'm getting a query output as follows from a table
RowId QuestionGroupId QuestionId Answer
1 2 1 Single
2 2 2 With Kids
3 2 3 Not At All
4 3 1 Single
5 3 2 With Kids
6 3 3 Occasionally Smoke
But the result I would Like to get is as something follows
RowId QuestionGroupId ValueSet
1 2 [{QuestionId:1,Answer:Single},QuestionId:2,Answer:WithKids},QuestionId:3,Answer:Nt at all}]
2 3 [{QuestionId:1,Answer:Single},QuestionId:2,Answer:WithKids},QuestionId:3,Answer:Occasionally Smoke}]
So how to I convert the rows of record to JSON using SQL JSON ability.
Using FOR JSON AUTO given me all in one row of record.Your help is appreciated.
I don't really get what you're doing with the RowId column, but you should be able to do something like this with a correlated subquery to get what you're after
;with src
(
RowId,
QuestionGroupId,
QuestionId,
Answer
) as
(
select 1, 2, 1, 'Single'
union all select 2, 2, 2, 'With Kids'
union all select 3, 2, 3, 'Not At All'
union all select 4, 3, 1, 'Single'
union all select 4, 3, 2, 'With Kids'
union all select 4, 3, 3, 'Occasionally Smoke'
)
select
QuestionGroupId,
(
select i.QuestionId, i.Answer
from src i
where o.QuestionGroupId = i.QuestionGroupId
order by QuestionId
for json auto
) as ValueSet
from src o
group by QuestionGroupId
How to split the string and grouping them by splited token?
I want to get that grouping splited token's each count.
I have a varchar column and it store a string which can split by ',' .
below is the row data of the column. (column name is LogData)
[LogData]
1,2,3,4
1,3,1,9
2,1,3
6,2
And then i want to show(select) like below.
[token] [count]
1 : 4
2 : 3
3 : 3
4 : 1
6 : 1
9 : 1
If possible, then may i have a answer about this with some explanation? (I'm not skilled in db)
Using the and adapting the comment from undefined_variable the correct query looks like this:
SELECT value,COUNT(*) FROM
(SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(t0.logdata, ',', n.n), ',', -1) value
FROM t0 CROSS JOIN
(
SELECT a.N + b.N * 10 + 1 n
FROM
(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
ORDER BY n
) n
WHERE n.n <= 1 + (LENGTH(t0.logdata) - LENGTH(REPLACE(t0.logdata, ',', '')))
ORDER BY value) nt0 GROUP BY value
I want to copy the third and the forth column but change the second column. What should I do? I want to know how to write the sql query. Thank you.
for example:
table1:
1, 1, aaa, bbb
2, 1, ads, bff
3, 1, awq, bcc
and I want table1 finally to be:
1, 1, aaa, bbb
2, 1, ads, bff
3, 1, awq, bcc
4, 2, aaa, bbb
5, 2, ads, bff
6, 2, awq, bcc
(the first column is id)
This should work:
insert into table1 (column2,column3,column4)
select 2,column3, column4
from table1 where column2 = 1
As you suggest:
select (#cnt:=#cnt + 1) as RowNumber,a.c1,a.c2,a.c3 from
(select 1 as id, 1 as c1, 'aaa' as c2, 'bbb'as c3 union all
select 2, 1, 'ads', 'bff' union all
select 3, 1, 'awq', 'bcc'
union all
select 1 as id, 1 as c1, 'aaa' as c2, 'bbb'as c3 union all
select 2, 1, 'ads', 'bff' union all
select 3, 1, 'awq', 'bcc') as a
cross JOIN
(select #cnt:=0) as tmp
RESULT:
1 1 aaa bbb
2 1 ads bff
3 1 awq bcc
4 1 aaa bbb
5 1 ads bff
6 1 awq bcc
I have this MySQL table :
create table example (
My_Id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
My_Integer INT UNSIGNED DEFAULT 0
) ENGINE=InnoDB
Suppose this table to be populated like that :
SELECT * FROM `example`
My_Id My_Integer
1 10
2 1
3 3
4 152
5 16
6 481
7 128
My goal is to retrieve, from an user input, which integer is not in my table 'example'.
For example, if the user enter 1, 3, 10, the result should be empty.
If the user enter 1, 2, 3, 10, the result should be "2".
I can't find a way to do that, other than to do one MySQL request per integer in order to know if the number is in the table 'example'.
Do someone know a way ?
Select numberToMatch
from example as a
right outer join (
select 1 as numberToMatch union all
select 2 union all
select 3 union all
select 10
) as b
on b.numberToMatch = a.My_Integer
where a.My_Integer is null
Using right outer join and select those null record in the left table.
You could genereate tally table and use OUTER JOIN:
SELECT t.n
FROM (
SELECT a.N + b.N * 10 + c.N * 100 + 1 n
FROM (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) c
) t
LEFT JOIN example e
ON t.n = e.My_Integer
WHERE t.n IN (1,2,3,10) -- here goes numbers
AND e.My_Integer IS NULL;
LiveDemo
Output:
╔═══╗
║ n ║
╠═══╣
║ 2 ║
╚═══╝
It will work in range 1-999. You could expand it if needed.
Another way is to use UNION ALL:
SELECT s.col
FROM (SELECT 1 AS col
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 10) AS s
LEFT JOIN example e
ON s.col = e.My_Integer
WHERE e.My_Integer IS NULL;
LiveDemo2