How to make sql query? - mysql

Here is the structure of table Likes:
id(int 11)
idn(varchar 10)
type (enum ('up','down'))
Here is the structure of table News:
id(int 11)
idn(varchar 10)
header (varchar 100)
date(datetime)
To show news, I use sql query:
SELECT header FROM News n left join Likes l on l.idn=n.idn ORDER by n.date
But now I want to select headers news From table News with order by desc count rows in table Likes with type = up.
How can I do this?

Here is a query to get top liked headers for each day. If you need TOP for all dates remove n.date from the ORDER BY:
SELECT header FROM News as n
LEFT JOIN
(
Select idn,Count(*) as UpLikes FROM Likes WHERE type='up' GROUP BY idn
) as l
ON l.idn=n.idn
ORDER BY n.date,l.UpLikes DESC

Why don't you use this:
SELECT id, idn, header, LikeCount
FROM
(
SELECT id, idn, header, (SELECT COUNT(1) FROM [Likes]) AS [LikeCount]
FROM [News]
)
ORDER By [LikeCount]

SELECT n.header, COUNT(i.`id`) as like_count
FROM Likes l LEFT JOIN News n ON n.idn = l.idn
WHERE l.`type` = 'up'
ORDER BY like_count DESC

Related

Searching and Sorting Using MySQL Inner Join

I guess I can't explain my problem properly. I want to explain this to you with a picture.
Picture 1
In the first picture you can see the hashtags in the trend section. These hashtags are searched for the highest total and it is checked whether the date has passed. If valid data is available, the first 5 hashtags are taken.
Picture 2
In the second picture, it is checked whether the posts in the hashtag are in the post, if any, the oldest date value is taken, LIMIT is set to 1 and the id value from the oyuncular table is matched with sid. Thus, the name of the person sharing can be accessed.
Picture 3
My English is a little bad, I hope I could explain it properly.
SELECT
social_trend.hashtag,
social_trend.total,
social_trend.tarih,
social_post.sid,
social_post.tarih,
social_post.post,
oyuncular.id,
oyuncular.isim
FROM
social_trend
INNER JOIN
social_post
ON
social_post.post LIKE '%social_trend.hashtag%' ORDER BY social_post.tarih LIMIT 1
INNER JOIN
oyuncular
ON
oyuncular.id = social_post.sid
WHERE
social_trend.tarih > UNIX_TIMESTAMP() ORDER BY social_trend.total DESC LIMIT 5
YOu should use a sibquery
and add a proper join between subqiery and social_trend
(i assumed sing both sid)
SELECT
social_trend.hashtag,
social_trend.total,
social_trend.tarih,
t.sid,
t.tarih,
t.post,
oyuncular.id,
oyuncular.isim
FROM (
select social_post.*
from social_post
INNER JOIN social_trend ON social_post.post LIKE concat('%',social_trend.hashtag,'%' )
ORDER BY social_post.tarih LIMIT 1
) t
INNER JOIN social_trend ON social_trend.hashtag= t.post
INNER JOIN oyuncular ON oyuncular.id = t.sid
WHERE
social_trend.tarih > UNIX_TIMESTAMP() ORDER BY social_trend.total DESC LIMIT 5
but looking to your new explanation and img seems you need
SELECT
t.hashtag,
t.total,
t.tarih_trend,
t.sid,
t.tarih,
t.post,
oyuncular.id,
oyuncular.isim
FROM (
select social_post.sid
, social_post.tarih
, social_post.post
, st.hashtag
, st.total
, st.tarih tarih_trend
from social_post
INNER JOIN (
select * from social_trend
WHERE social_trend.tarih > UNIX_TIMESTAMP()
order by total DESC LIMIT 5
) st ON social_post.post LIKE concat('%',st.hashtag,'%' )
ORDER BY social_post.tarih LIMIT 5
) t
INNER JOIN oyuncular ON oyuncular.id = t.sid

Combining two select statements without on clausule

I have two tables that are not related at all
First table is called pocetna_baner that stores 3 pictures that are going to be displayed on index page.
pocetna_baner table:
Second table is for blog and I want to take information of 3 blogs ordered by datum desc:
blog table
I tried using UNION, UNION ALL, JOIN without clauses, full outer join, but just cannot get it to work because I never had this situation where there is no on clause
union all with queries that have a different number of columns -> I searched for answers and got to this one which seemed okay but unfortunately couldn't get it to work
This is what I have by now
(SELECT null as blog_id, null as naslov, null as tekst1, null as kategorija, p.ime_slike FROM
pocetna_baner p )
UNION ALL
(SELECT b.blog_id, b.naslov, b.tekst1, b.kategorija ,null as ime_slike
FROM blog b ORDER BY b.datum DESC LIMIT 3 )
And result is this
My expected output is only to take b.blog_id, b.naslov, b.tekst1, b.kategorija FROM blog b ordered by datume desc limit 3 and add column with ime_slike from second table
You can construct the ON clause by creating 1 counter column in each table and matching on them:
select
b.blog_id, b.naslov, b.tekst1, b.kategorija, p.ime_slike
from (
select
blog_id, naslov, tekst1, kategorija,
(#row_number1:=#row_number1 + 1) num
from blog, (select #row_number1:=0) t
order by datum desc limit 3
) b left join (
select ime_slike,
(#row_number2:=#row_number2 + 1) num
from pocetna_baner, (select #row_number2:=0) t
order by id limit 3
) p on p.num = b.num
If you are sure that the ids in the table pocetna_baner have values 1, 2 and 3 then you can simplify to this:
select
b.blog_id, b.naslov, b.tekst1, b.kategorija, p.ime_slike
from (
select
blog_id, naslov, tekst1, kategorija,
(#row_number1:=#row_number1 + 1) num
from blog, (select #row_number1:=0) t
order by datum desc limit 3
) b left join pocetna_baner p
on p.id = b.num
I have just given an example by this code.
Please change as per needs.
SELECT * FROM (
SELECT p.ime_slike,null as blog_id,null as naslov,null as kategorija FROM
pocetna_baner p
UNION ALL
SELECT b.blog_id, b.naslov, b.tekst1, b.kategorija ,null as ime_slike
FROM blog b
ORDER BY datum DESC LIMIT 3 ) AS k

Postgres JSON Join, Union

I have posts, swipes, notifications. I want to
sort posts by their score
delete swiped ones
join notifications with posts and put joined ones as top scores
So far I have done the first two but couldn't add the notifications as the first elements to the result. This is the working query of the first two.
SELECT posts.id, posts.created_at, posts.data, ((posts.data)->>'score')::NUMERIC as score
FROM posts
WHERE NOT EXISTS (
SELECT *
FROM swipes
WHERE ((swipes.data)->>'post_id')::INT = posts.id AND ((swipes.data)->>'user_id')::INT = 32)
ORDER BY (data)->>'score'
LIMIT 5
I tried LEFT JOIN for adding notifications but couldn't do it.
SELECT posts.id, posts.created_at, posts.data, ((posts.data)->>'score')::NUMERIC as score
FROM posts
WHERE NOT EXISTS (
SELECT *
FROM swipes
WHERE ((swipes.data)->>'post_id')::INT = posts.id AND ((swipes.data)->>'user_id')::INT = 32)
-- The part below is new
UNION ALL
SELECT notifications.id, notifications.created_at, notifications.data, 9999999 AS score
FROM notifications
--- THIS GIVES ERROR ---
LEFT JOIN posts USING (notifications.data)->>'post_id')
WHERE ((notifications.data)->>'user_id')::INT = 32
-- After join order by score
ORDER BY score
LIMIT 5
notifications has a column named data type json. notifications.data->post_id should joined by posts.id with it by score 9999999. where notifications.data->user_id should be equal to 32.
If you want the rows from table 'notifications' in addition to the rows from table 'posts', then you should UNION:
SELECT id, created_at, data, (data->>'score')::numeric AS score
FROM posts
WHERE NOT EXISTS (
SELECT 1
FROM swipes
WHERE ((swipes.data)->>'post_id')::int = posts.id
AND ((swipes.data)->>'user_id')::int = 32)
UNION ALL
SELECT id, created_at, data, 9999999 AS score
FROM notifications
LEFT JOIN posts USING (notifications.data)->>'post_id')
WHERE (data->>'user_id')::int = 32
-- After join order by score
ORDER BY score
LIMIT 5;
If instead you want to add the columns of table 'notifications' to those of table 'posts, then you should JOIN:
SELECT p.id, p.created_at, p.data, (p.data->>'score')::numeric AS score
n.id, n.created_at, n.data
FROM posts p
JOIN notifications n ON n->>'post_id' = p->>'post_id' -- guessing here
WHERE NOT EXISTS (
SELECT 1
FROM swipes
WHERE ((swipes.data)->>'post_id')::int = p.id
AND ((swipes.data)->>'user_id')::int = 32)
WHERE (n.data->>'user_id')::int = 32
ORDER BY score
LIMIT 5;

Left join order by

I have property pictures in table with their sort_order starting from 0 to number of pictures.
What I would like to do is select pictures but I would like it to start from 2.
My approach was:
SELECT * FROM property_photos AS pp1
JOIN property_photos AS pp2 ON pp1.p_id = pp2.p_id
where pp2.sort_order =2
and pp2.sort_order <2
and pp1.sort_order >2
and pp1.p_id = 3
So what I am trying to gain here is the sort order would be like 2,0,1,3,4,5,6,7
so I need a self join but my query doesn't work
you don't need a join on this,
SELECT *
FROM property_photos
WHERE p_id = 3
ORDER BY (sort_order = 2) DESC, sort_order

group by month and year, count from another table

im trying to get my query to group rows by month and year from the assignments table, and count the number of rows that has a certain value from the leads table. they are linked together as the assignments table has an id_lead field, which is the id of the row in the leads table.
d_new would be a count of the assignments for leads for the month whose website is newsite.com
d_subprime would be a count of the assignments for leads for the month whose website is not newsite.com
here are the tables being used:
`leads`
id (int)
website (varchar)
`assignments`
id_lead (int)
date_assigned (int)
heres my query which is not working:
SELECT
MONTHNAME(FROM_UNIXTIME(a.date_assigned)) as d_month,
YEAR(FROM_UNIXTIME(a.date_assigned)) as d_year,
(select COUNT(*) from leads where website='newsite.com' ) as d_new,
(select COUNT(*) from leads where website!='newsite.com') as d_subprime
FROM assignments as a
left join leads as l on (l.id = a.id_lead)
where id_dealership='$id_dealership2'
GROUP BY
d_month,
d_year
ORDER BY
d_year asc,
MONTH(FROM_UNIXTIME(a.date_assigned)) asc
$id_dealership is a variable containing a id of the dealership im trying to view the count for.
any help would be greatly appreciated.
You can sort of truncate your timestamps to months and use the obtained values for grouping, then derive the necessary date parts from them:
SELECT
YEAR(d_yearmonth) AS d_year,
MONTHNAME(d_yearmonth) AS d_month,
…
FROM (
SELECT
LAST_DAY(FROM_UNIXTIME(a.date_assigned)) as d_yearmonth,
…
FROM assignments AS a
LEFT JOIN leads AS l ON (l.id = a.id_lead)
WHERE id_dealership = '$id_dealership2'
GROUP BY
d_yearmonth
) AS s
ORDER BY
d_year ASC,
MONTH(d_yearmonth) ASC
Well, LAST_DAY() doesn't really truncate a timestamp, but it does turn all the values belonging to the same month into the same value, which is basically what we need.
And I guess the counts should be related to the rows you are actually selecting, which is not what your subqueries are. Something like this might do:
…
COUNT(d.website = 'newsite.com' OR NULL) AS d_new,
/* or: COUNT(d.website) - COUNT(NULLIF(d.website, 'newsite.com')) AS d_new */
COUNT(NULLIF(d.website, 'newsite.com')) AS d_subprime
…
Here's the entire query with all the modifications mentioned:
SELECT
YEAR(d_yearmonth) AS d_year,
MONTHNAME(d_yearmonth) AS d_month,
d_new,
d_subprime
FROM (
SELECT
LAST_DAY(FROM_UNIXTIME(a.date_assigned)) as d_yearmonth,
COUNT(d.website = 'newsite.com' OR NULL) AS d_new,
COUNT(NULLIF(d.website, 'newsite.com')) AS d_subprime
FROM assignments AS a
LEFT JOIN leads AS l ON (l.id = a.id_lead)
WHERE id_dealership = '$id_dealership2'
GROUP BY
d_yearmonth
) AS s
ORDER BY
d_year ASC,
MONTH(d_yearmonth) ASC
This should do the trick:
SELECT
YEAR(FROM_UNIXTIME(a.date_assigned)) as d_year,
MONTHNAME(FROM_UNIXTIME(a.date_assigned)) as d_month,
l.website,
COUNT(*)
FROM
assignments AS a
INNER JOIN leads AS l on (l.id = a.id_lead) /*are you sure, that you need a LEFT JOIN?*/
WHERE id_dealership='$id_dealership2'
GROUP BY
d_year, d_month, website
/*an ORDER BY is not necessary, MySQL does that automatically when grouping*/
If you really need a LEFT JOIN, be aware that COUNT() ignores NULL values. If you want to count those as well (which I can't imagine to make sense) write it like this:
SELECT
YEAR(FROM_UNIXTIME(a.date_assigned)) as d_year,
MONTHNAME(FROM_UNIXTIME(a.date_assigned)) as d_month,
l.website,
COUNT(COALESCE(l.id, 1))
FROM
assignments AS a
LEFT JOIN leads AS l on (l.id = a.id_lead)
WHERE id_dealership='$id_dealership2'
GROUP BY
d_year, d_month, website
Start with
SELECT
MONTHNAME(FROM_UNIXTIME(a.date_assigned)) as d_month,
YEAR(FROM_UNIXTIME(a.date_assigned)) as d_year,
SUM(IF(l.website='newsite.com',1,0) AS d_new,
SUM(IF(l.website IS NOT NULL AND l.website!='newsite.com',1,0) AS d_subprime
FROM assignments AS a
LEFT JOIN leads AS l ON l.id = a.id_lead
WHERE id_dealership='$id_dealership2'
GROUP BY
d_month,
d_year
ORDER BY
d_year asc,
MONTH(FROM_UNIXTIME(a.date_assigned)) asc
and work from here: The field id_dealership is neither in leads nor in assignments, so you need more work.
If you edit your question to account for id_dealership we might be able to help you further.