Sorry but I am not sure how to phrase this question or if it is possible but basically I am using a select statement in which I would like to display a column showing a count of when a criteria is met. For example
SELECT pageID, isHome, if(ishome = 1, 'count?', 0) AS Passed
FROM pages
I would like the passed column to show a running count kind of like this
PageID | ishome | passed
10031 | 0 | 0
10032 | 1 | 1
10033 | 1 | 2
10034 | 1 | 3
Thank you for any help
Try something like the following (untested)
select a.pageid, a.ishome, sum(b.ishome) passed
from
pages a join pages b
on a.pageid>= b.pageid
group by a.pageid, a.ishome
order by a.pageid
Not sure but I think this is want you want.
SELECT pageID, isHome,
case when(ishome = 1)
then count(*)
else 0
end Passed FROM Table1
group by pageID;
sqlfiddle
OR if you want the number of passed pages
SELECT isHome,
case when(ishome = 1)
then count(*)
else 0
end Passed FROM Table1
group by isHome;
sqlfiddle
SELECT pageID, isHome, count(*) AS Passed
FROM pages
where ishome = 1
GROUP BY PageID
DEMO
if you want show all result then use this
SELECT pageID, isHome, if(ishome = 1, count(*), 0) AS Passed
FROM pages
group by pageID,ishome ;
DEMO
Try something like this
SELECT pageID, isHome,
CASE isHome
WHEN 1 THEN SELECT COUNT(*) FROM pages p
WHERE p.isHome = 1 AND p.pageID <= pageID
ELSE 0
END as passed
FROM pages
ORDER BY pageID ASC
Related
I have a sliders table. It is something that looks like this:
+----+-----------+-----------+
| id | video_url | image_url |
+----+-----------+-----------+
| 1 | null | imgurl1 |
+----+-----------+-----------+
| 2 | null | imgurl2 |
+----+-----------+-----------+
| 3 | null | imgurl3 |
+----+-----------+-----------+
| 4 | vidurl1 | null |
+----+-----------+-----------+
I can achieve what I want using this query:
(SELECT * FROM sliders WHERE image_url IS NOT NULL LIMIT 1)
UNION
(SELECT * FROM sliders WHERE video_url IS NOT NULL LIMIT 1)
UNION
(SELECT * FROM sliders)
Basically, the order I want is:
First Image
First Video
...
Everything else
So based on the example, the result should be (based on the id) is [1,4,2,3].
Is this possible to recreate without using UNION clause?
By the way, I am using Ruby on Rails on this project and currently using find_by_sql to execute the query. If you can help me use ActiveRecord instead, that would be great.
As of now, I can't see a way to union tables when using ActiveRecord.
Your query is no solution for the problem given. A query result is only then guaranteed to be sorted when you apply ORDER BY, which you don't. Your query boils down to a mere
SELECT * FROM sliders;
Even if you happen to get the rows in the desired order with your query now, this can be already different the next time you run it.
(Apart from this, you are applying LIMIT 1 without an ORDER BY clause, which just picks a record arbitrarily. You could get any of the image urls with the first subquery.)
You need an ORDER BY clause in which you must check whether the row's ID is the first image or the first video:
SELECT *
FROM sliders
ORDER BY
id = (SELECT MIN(id) FROM sliders WHERE image_url IS NOT NULL) DESC,
id = (SELECT MIN(id) FROM sliders WHERE video_url IS NOT NULL) DESC,
id;
(This makes use of MySQL's true = 1, false = 0. By sorting in descending order, we get true before false.)
One method in MySQL is to use variables:
select s.*
from (select s.*,
(case when image_url is not null then #rn_i := #rn_i + 1 end) as rn_i,
(case when video_url is not null then #rn_v := #rn_v + 1 end) as rn_v,
from sliders cross join
(select #rn_i := 0, #rn_v := 0) params
order by id
) s
order by (rn_i = 1) desc, (rn_v = 1) desc, id asc;
I have a responses table which has a dataset like this...
id|resp_id|value|is_cleaned
1 1 Yes 0
2 1 No 1
3 2 No 0
I would like to get all the responses where is_cleaned = 1, if it doesnt exist i would like to get the uncleaned result. What i have tried so far is, grouping by resp_id and using CASE statement. Not sure what exactly to put in the CASE statement though.
What i have so far is
SELECT * FROM cleanedresponse GROUP BY case when is_cleaned = 1 then resp_id else resp_id end
I would like the following results
resp_id|value|is_cleaned
1 No 1
2 No 0
You can do that by getting the max(is_cleaned) for each resp_id first
select resp_id, max(is_cleaned)
from cleanedresponse
group by resp_id
and then using it as a filter in the original table
select t1.resp_id, t1.value, t1.is_cleaned
from cleanedresponse t1
join (
select resp_id, max(is_cleaned) as max_cleaned
from cleanedresponse
group by resp_id
) t2
on t1.resp_id = t2.resp_id and
t1.is_cleaned = t2.max_cleaned
So I have this bit of mysql that I'm trying to work out. My goal is to insert the count of a grouping into the primary records to tell me how many of each status is within the related table for the record, so the result might look like this:
| id | name | count1 | count2 |
------------------------------------
| 1 | primary 1 | 5 | 3 |
| 1 | primary 2 | 2 | 7 |
select * from primaryTable
left join (
select
case
when relationTable.relation_status_id = 1
then count(*)
END as count1,
case
when relationTable.relation_status_id = 2
then count(*)
END as count2
) relationTable
on relationTable.primary_id = primaryTable.id
I tried using a subquery to do it, which worked, but requires a select per count, which I'm trying to avoid.
Adding a group by to the subquery resulted in an error that more than one row was being returned.
In the subquery, rather than aggregate COUNT()s inside CASE, you may more easily use SUM() to add up the result of a boolean comparison (0 or 1) to return a result resembling a count.
SELECT
primaryTable.*,
count1,
count2
FROM
primaryTable
JOIN (
SELECT
primary_id,
-- Sum the results of a boolean comparison
SUM(relation_status_id = 1) AS count1,
SUM(relation_status_id = 2) AS count2
FROM relationTable
-- Group in the subquery
GROUP BY primary_id
-- Join the subquery to the main table by primary_id
) counts ON primaryTable.primary_id = counts.primary_id
Note that because MySQL treats the booleans the same as 0 or 1, the comparison relation_status_id = 1 returns 1 or 0. The syntax above isn't supported in every RDBMS. To be more portable, you would need to use a CASE inside SUM() to explicitly return an integer 1 or 0.
SUM(CASE WHEN relation_status_id = 1 THEN 1 ELSE 0 END) AS count1,
SUM(CASE WHEN relation_status_id = 2 THEN 1 ELSE 0 END) AS count2
Your original attempt has some syntax problems. Chiefly, it has no FROM clause, which is causing MySQL to think it should be treated as a scalar value and then complain that it returns more than one row.
I have a Table that tracks followers
FollowerUserId, FollowingUserId
1 2
2 1
3 1
4 1
1 5
I want to get all user that given Id follows and is followed by or Both.
for example for UserId 1,I want result to be: (FG: Following, FD: Followed, B: Both ways)
2,B
5,FG
3,FD
4,FD
i can easily get FG and FD by doing union
Select FollowerUserId, 'FD' From Table Where FollowingUserId =1
Union
Select FollowingUserId, 'FG' From Table Where FollowerUserId =1;
with above i get user 2 as
2,FG
2,FD
from above but I really need 2,B without UserId 2 duplicated.
How can this be done efficiently?
You can use aggregation on your basic query:
SELECT UserId,
(CASE WHEN COUNT(DISTINCT which) = 1 THEN MIN(which)
ELSE 'B'
END)
FROM (Select FollowerUserId as UserId, 'FD' as which From Table Where FollowingUserId = 1
Union ALL
Select FollowingUserId, 'FG' From Table Where FollowerUserId = 1
) f
GROUP BY UserId;
Consider:
SELECT(count(c.id),
case when(count(c.id) = 0)
then 'loser'
when(count(c.id) BETWEEN 1 AND 4)
then 'almostaloser'
when(count(c.id) >= 5)
then 'notaloser'
end as status,
...
When all is said and done, the query as a whole produces a set of results that look similar to this:
Count | status
--------|-------------
2 | almostaloser //total count is between 2 and 4
--------|-------------
0 | loser // loser because total count = 0
--------|-------------
3 | almostaloser //again, total count between 2 and 4
--------|-------------
What I would like to achieve:
a method to reatain the information from the above table, but add a third column that will give a total count of each status, something like
select count(c.id)
case when(count(c.id) = 0 )
then loser as status AND count how many of the total count does this apply to
results would look similar to:
Count | status |total_of each status |
--------|-------------|---------------------|
2 | almostaloser| 2 |
--------|-------------|---------------------|
0 | loser | 1 |
--------|-------------|---------------------|
3 | almostaloser| 2 |
--------|-------------|----------------------
I've been told this could be achieved using a derived table, but i've not yet been able to get them both, only one or the other.
This can be achieved with this query (you must place your original query as subquery in two places):
SELECT t1.*, t2.total_of_each_status
FROM (
-- put here your query --
) t1
INNER JOIN (
SELECT status, count(*) AS total_of_each_status
FROM (
-- put here your query --
) t2
GROUP BY status
) t2 ON t2.status = t1.status