Remove the line with the same name but different value - mysql

So basically I run this code in sql:
SELECT p.Nome as Nome_pub, a.Nome as Nome_area, COUNT(*) as total
FROM publicacao p, emprestimo e, area_tematica a
WHERE p.Id=e.Publicacao_Id and p.Area_Tematica_Id=a.Id and (Data_hora>='2021-01-01' AND Data_de_devolucao<='2021-06-31')
GROUP by p.Nome
ORDER BY Nome_area;
and I get the following output
Nome_pub
Nome_area
total
name1
a
1
name2
b
1
name3
c
1
name4
d
3
name5
d
2
name6
d
2
name7
e
1
but I want an output that gives me the max word3 based on word2 basically: (in my case remove line with "name5" and "name6"
Nome_pub
Nome_area
total
name1
a
1
name2
b
1
name3
c
1
name4
d
3
name7
e
1
is there any way to do this??
Thanks in advance!!

If ROW_NUMBER is available in your version.
SELECT Nome_pub, Nome_area, total
(
SELECT
p.Nome as Nome_pub
, a.Nome as Nome_area
, COUNT(*) as total
, ROW_NUMBER() OVER (PARTITION BY a.Nome ORDER BY COUNT(*) DESC) as RN
FROM publicacao p
JOIN emprestimo e
ON p.Id = e.Publicacao_Id
JOIN area_tematica a
ON a.Id = p.Area_Tematica_Id
WHERE ( Data_hora >= DATE '2021-01-01' AND
Data_de_devolucao < DATE '2021-07-01')
GROUP by p.Nome, a.Nome
) q
WHERE RN = 1
ORDER BY Nome_area;

Related

Get the row with latest date after inner join

I have this query:
SELECT
achievements.id,
achievements.name,
achievements.category,
userAchievements.createdAt
FROM
achievements
INNER JOIN
userAchievements ON userAchievements.achievementId = achievements.id
AND userAchievements.userId = 12
WHERE
achievements.type = 2
Result of this query is:
id
name
category
createdAt
8
First
1
2021-02-11
13
Second
2
2021-02-12
14
Third
4
2021-03-01
15
Fourth
4
2021-03-02
I have to leave only unique category with max createdAt field.
I need a query that will give the following result:
id
name
category
createdAt
8
First
1
2021-02-11
13
Second
2
2021-02-12
15
Fourth
4
2021-03-02
If I use group by then it returns row with id 14.
MySQL version - 5.7.33.
Achievements table:
id
name
category
8
First
1
13
Second
2
14
Third
4
15
Fourth
4
UserAchievements table:
id
achievementId
userId
createdAt
3
8
12
2021-02-11
7
13
12
2021-02-12
36
15
12
2021-03-02
40
14
12
2021-03-01
P.S.
I managed to write a query that solves the problem
SELECT
*
FROM
(SELECT
*,
IF(#prev <> category, #rn:=0, #rn),
#prev:=category,
#rn:=#rn + 1 AS rn
FROM
(SELECT
achievements.id,
achievements.name,
achievements.category,
userAchievements.createdAt
FROM
achievements
INNER JOIN userAchievements ON userAchievements.achievementId = achievements.id
AND userAchievements.userId = 12
WHERE
achievements.type = 2) as ach, (SELECT #rn:=0) rn, (SELECT #prev:='') prev
ORDER BY ach.createdAt DESC) t
WHERE
rn = 1
You can use window functions:
SELECT a.*
FROM (SELECT a.*,
ROW_NUMBER() OVER (PARTITION BY a.category ORDER BY a.created_at DESC) as seqnum
FROM achievements JOIN
userAchievements ua
ON ua.achievementId = a.id AND
ua.userId = 12
WHERE a.type = 2
) a
WHERE seqnum = 1;
This subquery basically search for all maximum dates, grouped by category.
SELECT MAX(_ua.createdAt) FROM `achievements` _a INNER JOIN user_achievements _ua ON _a.id = _ua.achievementId group by _a.category
So you maybe you can do :
SELECT a.* FROM achievements a
INNER JOIN user_achievements ua ON a.id = ua.achievementId
AND ua.createdAt IN (SELECT MAX(_ua.createdAt) FROM `achievements` _a INNER JOIN
user_achievements _ua ON _a.id = _ua.achievementId group by _a.category)

Getting Data from Database with multiple conditions

I have below mentioned table:
ID Type Date Status1 Status2 Status3
1 458 2018-01-01 15:04:06 AAA A B
2 471 2017-12-31 15:04:06 AAA A B
3 458 2018-01-15 15:04:06 BBC C D
5 458 2018-01-18 15:04:06 AAA X D
There are many same value in Type column, i want to fetch the data with below mentioned condition:
Where any value in Type (should have more than one time in table) have Status1 as AAA and other rows with same value in Type are greater than Previous Date, with Status2 as C and Status3 as D together or Status3 must be D.
Output:
ID Type Date Status1 Status2 Status3
1 458 2018-01-01 15:04:06 AAA A B
3 458 2018-01-15 15:04:06 BBC C D
5 458 2018-01-18 15:04:06 AAA X D
I am using below mentioned query:
SELECT a.ID,a.Type,a.Date,b.Status1,a.Status2,a.Status3
From Table1 a
inner join Table2 b
on a.abc=b.xyz
inner join Table2 c
on a.efg=c.xyz
GROUP BY a.Type
HAVING Count(a.Type)>0
AND b.Status1='AAA'
UNION SELECT a.ID,a.Type,a.Date,b.Status1,a.Status2,a.Status3
FROM Table1 a
inner join Table2 b
on a.abc=b.xyz
inner join Table2 c
on a.efg=c.xyz
GROUP BY a.Type
HAVING Count(a.Type)>0
AND a.Date > (SELECT Date From Table1 GROUP BY Type HAVING b.Status1='AAA' AND Count(Type)>0)
AND ( Status2='A' AND Status3='D' )
OR Status3='D';
You can try something like below
SELECT t.* FROM `t` INNER JOIN
(
SELECT `type` , COUNT(`type`) ct FROM t GROUP BY `type` HAVING ct > 1
) t1
ON t1.type = t.type ORDER BY DATE ASC
I hope this will return what you want.
Try this query .
Hope this will give you the desire output .
SELECT
ID ,
Type ,
Date ,
Status1 ,
Status2 ,
Status3
FROM
[Tabel_Name]
GROUP BY
Type
HAVING
Count(Type)>0
AND
Status1='AAA'
UNION
SELECT
ID ,
Type ,
Date ,
Status1 ,
Status2 ,
Status3
FROM
[Tabel_Name]
GROUP BY
Type
HAVING
Count(Type)>0
AND
Date > (SELECT Date From [Tabel_Name] GROUP BY Type HAVING Status1='AAA' AND Count(Type)>0)
AND
( Status2='C' AND Status3='D' )
OR
Status3='D'

Mysql group_concat for count in sub query using parent filed is not allowed

I need to process album count for each of the country per artist; however, I have a problem once I do group_concat for count in mysql, I search a bit in stackoverflow, I found I have to do sub select for group_concat. The problem is once I do the sub select in from I can not use a.id from the parent from filed table. I got error like following Unknown column 'a.id' in 'where clause'
This is the query:
SELECT a.seq_id, a.id
(SELECT GROUP_CONCAT(cnt) AS cnt FROM (
SELECT CONCAT_WS('-', mgr.country_code, count(mgr.media_id)) AS cnt
FROM music_album_artists AS ma
JOIN media_geo_restrict AS mgr ON ma.album_id = mgr.media_id
WHERE ma.artist_id = a.id
GROUP BY mgr.country_code
) count_table
) AS album_count
FROM music_artist AS a
WHERE a.seq_id > 0 and a.seq_id < 10000
The sample data in tables:
music_artists:
seq_id id name
1 1 Hola
2 2 Vivi
music_album_artists:
id artist_id album_id
1 1 1
2 1 2
3 1 5
4 1 10
5 2 2
6 2 10
6 2 1
media_geo_restrict:
album_id country_code
1 BE
1 CA
1 DE
1 US
2 CH
2 CA
2 CH
5 DE
10 US
The result I would like to have
seq_id id album_count
1 1 BE--1,CA--2,CH--1,DE--1,US--1
2 2 CA--1,US--2,CH--1
Here is what you need:
select seq_id, id, group_concat(concat(country_code, '--', qtd))
from (
select ma.seq_id, ma.id,
mgr.country_code, count(*) qtd
from music_artists ma
inner join music_album_artists maa
on ma.id = maa.artist_id
inner join media_geo_restrict mgr
on maa.album_id = mgr.album_id
where ma.seq_id > 0 and ma.seq_id < 10000
group by ma.seq_id, ma.id, ma.name,
mgr.country_code
) tb
group by seq_id, id
Here is the working sample: http://sqlfiddle.com/#!9/ff8b5/8
Try this and tell me:
SELECT a.seq_id, a.id, GROUP_CONCAT(cnt) AS cnt
FROM music_artist AS a,
(
SELECT ma.artist_id, CONCAT_WS('-', mgr.country_code, count(mgr.media_id)) AS cnt
FROM music_album_artists AS ma
JOIN media_geo_restrict AS mgr ON ma.album_id = mgr.album_id
GROUP BY mgr.country_code
) AS count_table
WHERE a.seq_id > 0 and a.seq_id < 10000
and a.id=count_table.artist_id
group by a.id

SQL: finding differences between rows

I want to count how many times each user has rows within '5' of eachother.
For example, Don - 501 and Don - 504 should be counted, while Don - 501 and Don - 1600 should not be counted.
Start:
Name value
_________ ______________
Don 1235
Don 6012
Don 6014
Don 6300
James 9000
James 9502
James 9600
Sarah 1110
Sarah 1111
Sarah 1112
Sarah 1500
Becca 0500
Becca 0508
Becca 0709
Finish:
Name difference_5
__________ _____________
Don 1
James 0
Sarah 2
Becca 0
Use the ABS() function, in conjunction with a self-join in a subquery:
So, something like:
SELECT name, COUNT(*) / 2 AS difference_5
FROM (
SELECT a.name name, ABS(a.value - b.value)
FROM tbl a JOIN tbl b USING(name)
WHERE ABS(a.value - b.value) BETWEEN 1 AND 5
) AS t GROUP BY name
edited as per Andreas' comment.
Assuming that each name -> value pair is unique, this will get you the count of times the value is within 5 per name:
SELECT a.name,
COUNT(b.name) / 2 AS difference_5
FROM tbl a
LEFT JOIN tbl b ON a.name = b.name AND
a.value <> b.value AND
ABS(a.value - b.value) <= 5
GROUP BY a.name
As you'll notice, we also have to exclude the pairs that are equal to themselves.
But if you wanted to count the number of times each name's values came within 5 of any value in the table, you can use:
SELECT a.name,
COUNT(b.name) / 2 AS difference_5
FROM tbl a
LEFT JOIN tbl b ON NOT (a.name = b.name AND a.value = b.value) AND
ABS(a.value - b.value) <= 5
GROUP BY a.name
See the SQLFiddle Demo for both solutions.
Because the OP also wants de zero counts, we'll need a self- left join. Extra logic is needed if one person has two exactly the same values, these should also be counted only once.
WITH cnts AS (
WITH pair AS (
SELECT t1.zname,t1.zvalue
FROM ztable t1
JOIN ztable t2
ON t1.zname = t2.zname
WHERE ( t1.zvalue < t2.zvalue
AND t1.zvalue >= t2.zvalue - 5 )
OR (t1.zvalue = t2.zvalue AND t1.ctid < t2.ctid)
)
SELECT DISTINCT zname
, COUNT(*) AS znumber
FROM pair
GROUP BY zname
)
, names AS (
SELECT distinct zname AS zname
FROM ztable
GROUP BY zname
)
SELECT n.zname
, COALESCE(c.znumber,0) AS znumber
FROM names n
LEFT JOIN cnts c ON n.zname = c.zname
;
RESULT:
DROP SCHEMA
CREATE SCHEMA
SET
CREATE TABLE
INSERT 0 14
zname | znumber
-------+---------
Sarah | 3
Don | 1
Becca | 0
James | 0
(4 rows)
NOTE: sorry for the CTE, I had not seen th mysql tag,I just liked the problem ;-)
SELECT
A.Name,
SUM(CASE WHEN (A.Value < B.Value) AND (A.Value >= B.Value - 5) THEN 1 ELSE 0 END) Difference_5
FROM
tbl A INNER JOIN
tbl B USING(Name)
GROUP BY
A.Name

SQL COUNT & GROUP BY

I have this table
---ID----NAME----INVITED_BY---
1 A
2 B 1
3 C 1
4 D 2
all I want is to get the result:
---ID----NAME------INVITES---------
1 A 2 (COUNT OF INVITED_BY)
2 B 1
3 C 0
4 D 0
You could do a self join to count the number of persons invited:
select yt.id
, yt.name
, count(distinct inv_by.id) as invites
from YourTable yt
left join
YourTable inv_by
on yt.id = inv_by.invited_by
group by
yt.id
, yt.name