Make single query for news with comment counter - sql

I have two tables: news and comments.
I need to write a query for news content and comments count.
I've tried
SELECT
news.id, news.title, news.date, news.author_name, news.short_content,
COUNT(com.comment)
FROM
php_base.news
LEFT JOIN
php_base.comments AS com ON news.id = com.news_id
ORDER BY
date DESC
LIMIT 10
I guess there should be a lot of "AS". Anybody can help me? Thanks

You are missing a GROUP BY:
SELECT n.id, n.title, n.date, n.author_name, n.short_content,
COUNT(c.comment) as cnt
FROM php_base.news n LEFT JOIN
php_base.comments c
ON n.id = c.news_id
GROUP BY n.id, n.title, n.date, n.author_name, n.short_content,
ORDER BY n.date DESC LIMIT 10

Related

Combining two sql queries into one to get most popular questions & answers in single table from SEDE

I have a query to get the most popular questions from the SEDE by
SELECT TOP 10
'https://stackoverflow.com/questions/' + CONVERT(VARCHAR, Posts.Id) as url,
(ViewCount / (SELECT - DATEDIFF(DAY, GETDATE(), CreationDate))) AS ave_views_per_day,
Body as QUESTION,
Posts.Id,
Title
FROM
Posts
LEFT JOIN
PostTags ON Posts.Id = PostTags.PostId
LEFT JOIN
Tags ON PostTags.TagId = Tags.Id
WHERE
TagName IN ('##tag##')
AND ViewCount > 10000
ORDER BY
ave_views_per_day DESC
I have an additional query to get the highest scoring answer given a question id:
SELECT
'https://stackoverflow.com/questions/' + CONVERT(VARCHAR, Id) as url, HighestScoringAnswer
FROM
(SELECT TOP 1
Id, Body AS HighestScoringAnswer,
DENSE_RANK() OVER (ORDER BY Score DESC) Rank
FROM
(SELECT p.Id, p.ParentId, p.Body, p.Score
FROM Posts p
WHERE p.ParentId = ##QuestionId##) x
ORDER BY
Rank ASC) x
How can I combine these queries such that the ##QuestionId## from the second query is sourced from the Posts.Id from the first query, and the resulting HighestScoringAnswer column is added to the results of the first query? I tried using the Union operation but could not figure out how to "pass" the Id from one query to the other.
You have to make a JOIN between both queries (questions and answers); not an UNION (an UNION return the rows from the first query plus the rows from second query, excluding duplicated rows; but you want the top ten questions and more scored answer for each one in the same row).
Try this query, I think this is the query you are looking for:
SELECT DISTINCT TOP 10
'https://stackoverflow.com/questions/' + CONVERT(VARCHAR, q.Id) as url,
(q.ViewCount / -DATEDIFF(DAY, GETDATE(), q.CreationDate)) AS ave_views_per_day,
q.Body as QUESTION,
q.Id,
q.Title,
FIRST_VALUE(a.Body) OVER (PARTITION BY q.id ORDER BY a.Score DESC) AS HighestScoringAnswer
FROM Posts q
LEFT JOIN Posts a ON q.id = a.ParentId
WHERE q.PostTypeId = 1
AND q.Tags LIKE '%postgresql%'
AND q.ViewCount > 10000
ORDER BY ave_views_per_day DESC;

Removing duplicates *after* ordering in a SQL query

I have the following SQL query:
select
id,
name
from
project
inner join job on project.id = job.project_id
where
job.user_id = 'me'
order by
project.modified desc
limit 10
The idea is to get information about the 10 most recently used projects for a given user.
The problem is that this can return duplicates in the case where multiple jobs have the same project. Instead of having duplicates, I want to order all rows by modified desc, remove duplicates based on id and name, then limit to 10.
I've not been able to figure out how to achieve this. Can anyone point me in the right direction?
You are getting duplicates because of the join. As you only want columns from the project table (I assume id and name are from that table), not creating the duplicates in the first place would be better than removing them after the join:
select p.id,
p.name
from project p
where exists (select *
from job job
where job.project_id = p.id
and job.user_id = 'me')
order by p.modified desc
limit 10
try this using row_number - it will work on postgresql
select * from
(select
id,
name,row_number() over(partition by id,name order by modified desc) as rn
from
project inner join job on project.id = job.project_id
where
job.user_id = 'me')a where rn=1 order by modified desc limit 10
Did you try SELECT DISTINCT?
select distinct
id,
name
from
project
inner join job on project.id = job.project_id
where
job.user_id = 'me'
order by
project.modified desc
limit 10
I ended up with the following, which seems to work fine:
select
p.id,
p.name
from
project p
inner join
(
select
j.id,
max(j.modified) as max_modified
from
job j
where
t.user_id = 'me'
group by
j.id
order by
max_modified desc
limit 10
) ids on p.id = ids.id
order by
max_modified desc

correct select statement for multiple tables

I'm trying to get the latest 5 titles from 3 tables, I think I might be going wrong somewhere in my statement.
Here is my statement
SELECT * FROM news N, blog B, comments C WHERE active='1' ASC LIMIT 5
After FROM you can only set 1 table where the results will come from. Moreover if you use keyword ASC you should also say the field you order by try:
SELECT * FROM news WHERE active='1' order by 'fieldnew' ASC
UNION ALL
(SELECT * FROM blog WHERE active='1' order by 'fieldblog' ASC)
UNION ALL
(SELECT * FROM comments WHERE active='1' order by 'fieldcommnet' ASC)
You need to make a join on three tables provided !
in sql-server:
select top 5 * from
(
select * from News N inner join blog B on N.id=B.id inner join comments C on C.id=N.id
)x
order <something>

explain this short SQL query

Can someone please explain me this SQL query. This shows me the popular stores, but it doesn't works well.
sql = "SELECT t.name, t.slug, tt.count
FROM ".$wpdb->prefix."terms AS t INNER JOIN ".$wpdb->prefix."term_taxonomy AS tt ON t.term_id = tt.term_id
WHERE
tt.taxonomy IN ('$tax_name')
AND tt.count > 0
GROUP BY tt.count DESC
ORDER BY RAND() LIMIT $the_limit";
It doesn't work well because you are exposing one of the major issues with MySQL aggregation, namely that there are no restrictions built in (this has to be MySQL since other RDBMS don't even allow it to parse).
You are getting random values for t.name and t.slug because you are GROUPing by tt.count but not doing anything with those other fields.
For advice on how to fix this, you need to share some sample data and desired output.
Your question is fairly vague, so I'll just answer what I can about the query. Maybe something will clue you in to what your solution is, since I'm not really even sure what your problem is.
SELECT
t.name, t.slug, tt.count
FROM ".$wpdb->prefix."terms AS t
INNER JOIN ".$wpdb->prefix."term_taxonomy AS tt
ON t.term_id = tt.term_id
WHERE
tt.taxonomy IN ('$tax_name')
AND tt.count > 0
GROUP BY
tt.count DESC
ORDER BY RAND()
LIMIT $the_limit
This joins the terms and term_taxonomy tables (with whatever install prefix was used, such as wp_ resulting in wp_terms) aliased as 't' and 'tt' elsewhere in the query.
The tables are joined such that 'term' records and 'term_taxonomy' records with the same term_id are linked.
The results are limited such that the term_taxonomy.taxonomy field is one of the values passed in the $tax_name variable.
The results are then condensed such that rows with the same term_taxonomy.count are collapsed together, ordered randomly, and only the first $the_limit entries are returned.
I believe you want something like this:
SELECT *
FROM (
SELECT t.name, t.slug, SUM(tt.count) AS cnt
FROM terms t
JOIN term_taxonomy tt
ON tt.term_id = t.term_id
WHERE tt.taxonomy IN ($tax_name)
AND tt.count > 0
GROUP BY
t.term_id
ORDER BY
cnt DESC
LIMIT 100
) q
ORDER BY
RAND()
LIMIT 20
This will give you 20 random tags / categories of the top 100.
For GROUP BY to work, you need to apply some kind of aggregating function to everything you're not GROUPing BY.
I assume what you want is the total count for each store:
sql = "SELECT t.name, t.slug, sum(tt.count) as count
FROM ".$wpdb->prefix."terms AS t
INNER JOIN ".$wpdb->prefix."term_taxonomy AS tt
ON t.term_id = tt.term_id
WHERE tt.taxonomy IN ('$tax_name')
GROUP BY tt.term_id
HAVING count > 0";

SQL query: select five most commented posts from different blogs

I have a following tables Blogs(id) and Posts(id, blog_id, comment_count)
I need to select five most commented posts from different blogs. It's quite easy to do with a function, but is it possible to do with some kind of basic SQL?
Here's the query in SQL Server dialect
select top 5 top_post.* from Blogs b
cross apply
(select top 1 * from Posts p
where p.blog_id = b.id
order by p.comment_count) top_post
order by top_post.comment_count
SELECT b.*, c.num_comments
FROM
(
SELECT TOP 5 blog_id, SUM(comment_count) as num_comments
FROM posts GROUP BY blog_id ORDER BY SUM(comment_count) DESC
)c
INNER JOIN Blogs b ON (b.id = c.blog_id)
UPDATE Hopefully it's what you need. It's not very fast though.
SELECT b.*, c.comment_count
FROM
(SELECT blog_id, comment_count ,
ROW_NUMBER() OVER(PARTITION by blog_id ORDER BY comment_count DESC) as rnum
FROM posts
)c
INNER JOIN Blogs b ON (b.id = c.blog_id)
WHERE c.rnum <=5;
As far as I know, there is no standard way to implement Select Top which is actually supported by the major dbms.
See the comparison of SQL dialects