How to count values with different where clauses on the same column? - mysql

I hate that I have to ask but I just cant handle it.
I have this table votes:
type=1 is an upvote, type=0 would be a downvote
I want this output:
[
{'video': 'best-of-mehrwert', 'upvote': 2, 'downvote': 0},
{...}
]
I am using medoo:
<?php
$votes = $database->query(
// 'SELECT COUNT(video) as votes, video FROM votes GROUP BY video, type'
'
SELECT video,COUNT(*) as counts
FROM votes
GROUP BY video,type;
'
)->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($votes);
which gives me
[{"video":"anlaesse","counts":"1"},{"video":"best-of-mehrwert","counts":"2"}]
How do I "add a column" like "upvotes" i.e. entries where type = 1 and the same with type = 0?

two variants:
select
video,
sum(case when type=1 then 1 else 0 end) as upvote,
sum(case when type=0 then 1 else 0 end) as downvote
from votes
group by video
and
select
video,
sum(type) as upvote,
sum(1-type) as downvote
from votes
group by video
http://www.sqlfiddle.com/#!9/c73f2a/5

I think it might be easiest to SUM up a 1 for each row where your criteria matches:
SELECT
video,
SUM(CASE type WHEN 1 THEN 1 ELSE 0 END) as upvotes,
SUM(CASE type WHEN 0 THEN 1 ELSE 0 END) as downvotes
FROM
votes
GROUP BY
video;
Note, you should omit type from the GROUP BY in order to get a single row back for each video.

You could use case expression to count only the type of votes you're interested in:
SELECT video,
COUNT(CASE type WHEN 1 THEN 1 END) as upvotes
COUNT(CASE type WHEN 0 THEN 1 END) as downvotes
FROM votes
GROUP BY video, type;

Related

Is it good to select the same column on multiple where condition mysql?

I'm thinking about counting the number of rows depending on each condition and put each result with alias. I don't know if it possible and good to do it this way. For example:
select
(select sum(buy) from order_db where stts=1) as buy1,
(select sum(buy) from order_db where stts=2) as buy2,
(select sum(buy) from order_db where stts=3) as buy3
from order_db
where date='2021-08-29' and user='john'
I've tried but got error in return. I'm a basic sql learner. Please help me with suggestion or a clue to find the answer.
Use conditional aggregation:
SELECT SUM(CASE WHEN stts=1 THEN buy ELSE 0 END) buy1,
SUM(CASE WHEN stts=2 THEN buy ELSE 0 END) buy2,
SUM(CASE WHEN stts=3 THEN buy ELSE 0 END) buy3
FROM order_db
WHERE date='2021-08-29' AND user='john';
If there are other values than 1, 2 and 3 for stts you may also add to the WHERE clause:
AND stts IN (1, 2, 3)
So basically, this sounds like you are in need of a "conditional count". This can be achived with the combination of SUM and the CASE WHEN operator.
Applied to your problem, the solution would be somethinge like this:
select
(sum(case when stts = 1 then buy else 0 end)) as buy1,
(sum(case when stts = 2 then buy else 0 end)) as buy2,
(sum(case when stts = 3 then buy else 0 end)) as buy3
from order_db
where date='2021-08-29' and user='john'

Sequelize Subtraction of counts

I am trying to get the count by subtracting all records that have false from all the records that have true. I am unable to replicate such a thing in Sequelize but I was able to create it in a raw query:
SELECT (SELECT Count(id)
FROM votes
WHERE up = true
AND id = 1) - (SELECT Count(id)
FROM votes
WHERE up = false
AND id = 1) AS votes
Based off the documentation, I do not see a way to do such a thing. Is there anything that I am missing?
This may be simpler for your js lib to handle
select count(case when up = true then 1 end) - count(case when up = false then 1 end)
from votes
where id = 1
then this previous answer should help I think:
https://stackoverflow.com/a/47397320/2067753
Note that the count() function ignores nulls, but using sum() instead of count can give the same end result:
select sum(case when up = true then 1 else 0 end) - sum(case when up = false then 1 else 0 end)
from votes
where id = 1
using group by:
select id, count(case when up = true then 1 end) - count(case when up = false then 1 end)
from votes
where id = 1
group by id

Get both results with one query

I want to get results for likes by a specific user-id and all likes and dislikes of a specific page id.
My structure looks like this:
`pages`: (id, title)
`pages_likes`: (id, page_id, uid, status)
If the status is -1 it's a dislike of a specific page, if it's 1 it's a like.
So, to get all likes this is my query:
SELECT COUNT(id) FROM pages_likes WHERE status = '1'
But now I also want to get if user-id 3 for example likes this page with
SELECT COUNT(id) FROM pages_likes WHERE status = '1' AND uid='3'
How can I achieve both in one query? I guess there has to be changed something right after the SELECT statement?
If you want to do this in a single query, use conditional aggregation:
SELECT SUM(CASE WHEN uid = '3' THEN 1 ELSE 0 END) AS threeLikes,
SUM(CASE WHEN uid <> '3' THEN 1 ELSE 0 END) AS otherLikes
FROM pages_likes
WHERE status = '1'
Another option would be to use a UNION, cf. the answer given by #bernie
Update:
If you want page likes and dislikes in the same query, you can try:
SELECT SUM(CASE WHEN uid = '3' AND status = '1' THEN 1 ELSE 0 END) AS threeLikes,
SUM(CASE WHEN uid <> '3' AND status = '1' THEN 1 ELSE 0 END) AS otherLikes
SUM(CASE WHEN uid = '3' AND status = '0' THEN 1 ELSE 0 END) AS threeDislikes,
SUM(CASE WHEN uid <> '3' AND status = '0' THEN 1 ELSE 0 END) AS otherDisikes
FROM pages_likes
I think this would work:
SELECT '' user, COUNT(id) likes
FROM pages_likes
WHERE status = '1'
GROUP BY 1
UNION ALL
SELECT uid user, COUNT(id) likes
FROM pages_likes
WHERE status = '1' AND uid='3'
GROUP BY 1
I would do it this way:
SELECT COUNT(*) AS total_likes, SUM(uid=3) AS uid3_likes
FROM pages_likes
WHERE status=1 AND page_id=1234
Re your comment:
Here's an example of showing total likes, and total dislikes. It's similar to the answer from #TimBiegeleisen.
SELECT SUM(status=1) AS total_likes,
SUM(CASE WHEN uid=3 AND status=1 THEN 1 END) AS uid3_likes
SUM(CASE WHEN uid=3 AND status=-1 THEN 1 END) AS uid3_dislikes
FROM pages_likes
WHERE page_id=1234

How to count by the value of a column in SQL?

Say I have a table called votes, and a column in that table called vote_type which can either be 0 or 1. How can I fetch the COUNT of vote_type where vote_type is 1?
Right now, I can select the count of vote_type overall, but not the count of vote_type where it is 1 or 0, via this query:
SELECT COUNT(votes.vote_id) AS vote_count
FROM votes
WHERE <some condition>
ORDER BY vote_count
How can I select the total number of vote_types, the number of vote_types = 1, the number of vote_types = 0, and the total vote_value (votetypes = 1 minus votetypes = 0), and order it by the total vote_value?
EDIT: Note that 1 & 0 are not intrinsic values of a vote, but boolean expressions for a positive vote and a negative vote.
I don't know what exactly are you trying to do, but if you want to count all the votes with Vote_Type=1
try
SELECT COUNT(votes.vote_id) AS vote_count
FROM votes
WHERE votes.vote_type=1
or if you need to sum the votes
SELECT SUM(votes.vote_type) AS vote_sum
FROM votes
WHERE votes.vote_type=1
SELECT COUNT(*) TotalVotes,
SUM(CASE WHEN vote_type = 1 THEN 1 ELSE 0 END) TotalVoteOne,
SUM(CASE WHEN vote_type = 0 THEN 1 ELSE 0 END) TotalVoteZero,
SUM(CASE WHEN vote_type = 1 THEN 1 ELSE 0 END) -
SUM(CASE WHEN vote_type = 0 THEN 1 ELSE 0 END) TotalVoteValue
FROM votes
-- WHERE ....
-- ORDER ....
When you say order it by the total vote_value -- it actually doesn't makes sense since the total number of rows in the result is only one.
You can also wrap this in a subquery,
SELECT TotalVotes,
TotalVoteOne,
TotalVoteZero,
(TotalVoteOne - TotalVoteZero) AS TotalVoteValue
FROM
(
SELECT COUNT(*) TotalVotes,
SUM(CASE WHEN vote_type = 1 THEN 1 ELSE 0 END) TotalVoteOne,
SUM(CASE WHEN vote_type = 0 THEN 1 ELSE 0 END) TotalVoteZero
FROM tableName
-- WHERE ....
-- ORDER BY TotalVoteValue DESC
) a
Try to start with something like this:
SELECT SUM(CASE WHEN votetype = 1 then 1 else 0 end) AS vote_count_1,
SUM(CASE WHEN votetype = 0 then 1 else 0 end) AS vote_count_0
FROM votes
WHERE <some condition>
ORDER BY vote_count
Edit: Added a net_vote column, which I think is the "vote1 minus vote0" number you are after.
Select
Sum(Case v.vote_type When 1 then 1 else -1 end) as net_vote
From
Votes v
Where
<some condition>
I've removed the order by, because this is only going to return one row.
$query = "SELECT *FROM votes WHERE vote_type=1 || vote_type=0";
$result = mysql_query($query);
$row = mysql_fetch_assoc($result);
$WhereVoteIsOne=$row['vote_type'];
foreach ($WhereVoteIsOne as $votesCount) { echo $votesCount."<br/>";}

Order by * where *

Sorry that my english isn't the best.
Is it possible to do a "where" in "order by".
Example :
ORDER BY
SUM(points),
SUM(points) WHERE type = 1,
SUM(goal),
SUM(goal) WHERE type = 1
So as first we sort by points.
If anyone has the same number of SUM(points), then we sort by SUM(points) where type = 1.
If anyone has the same number of SUM(points) and the same number of SUM(points) where type = 1, then we sort after SUM(goal).
If anyone has the same in all 3, then it have to sort by SUM(goal) where type = 1.
SUM(CASE WHEN type=1 THEN points ELSE 0 END)
etc.
you should of course add DESC on all order conditions, if you want the "best" first ;)
And the sqlFiddle
ORDER BY
SUM(points),
SUM(CASE WHEN type = 1 THEN points ELSE 0 END),
SUM(goal),
SUM(CASE WHEN type = 1 THEN goal ELSE 0 END)