Edit 2021: I want to explain this better.
I have a table named MyTable with two columns; one column named SortColumn type Integer and one column named ExpressionColumn type Boolean.
I want to get all rows, sorted by SortColumn in ascending order, after the last row where ExpressionColumn was True.
The types are not exact.
Eg. Table with rows represented as [SortColumn,ExpressionColumn], [0:True] will get [0:True], [0:True, 1:False] will get [], [0:True, 1:False, 2:True, 3:True] will get [3:True, 4:True].
Leaving the old question below so as not to invalidate given answers. It had too many extra details.
I want to select rows after than last row where column Number is 0.
So with this table,
Id | Number
------------
0 | 5
1 | 30
2 | 10
3 | 25
I want to get rows with Id 0 to 3 inclusive.
With this table,
Id | Number
------------
0 | 5
1 | 30
2 | 10
3 | 25
4 | 0
I want to get no rows at all.
With this table,
Id | Number
------------
0 | 5
1 | 30
2 | 10
3 | 25
4 | 0
5 | 0
6 | 30
I want to get row with Id 6.
SQL details: MySQL 5.6.
Retrieve separate records:
SELECT *
FROM transaction t1
WHERE Name LIKE '%Car Wash%'
AND NOT EXISTS ( SELECT NULL
FROM transaction
WHERE t1.id <= id
AND Name LIKE '%Car Wash%' -- maybe not needed? not specified
AND Price = 0 );
Retrieve their amount only:
SELECT COUNT(*)
FROM transaction t1
WHERE Name LIKE '%Car Wash%'
AND NOT EXISTS ( SELECT NULL
FROM transaction
WHERE t1.id <= id
AND Name LIKE '%Car Wash%'
AND Price = 0 );
fiddle
you can select
select
from my_table
where name like '%car%' and price > 0
and for count
select count(*)
from (
select
from my_table
where name like '%car%' and price > 0
) t
I interpret this question as "how many rows are there for "car wash" after the first row with price > 0". If so:
select count(*)
from (select t.*,
min(case when price = 0 then id end) over () as id_at_0
from transaction t
) t
where name = 'Car Wash' and id > id_at_0
SELECT * FROM MyTable myTable1
AND NOT EXISTS ( SELECT NULL FROM MyTable
WHERE myTable1.SortColumn <= SortColumn
AND ExpressionColumn = True );
Related
I have the following table structure
TABLE A
Productid price groupId
1 100 A
2 99 A
3 0 A
4 50 B
5 49 B
6 0 B
I populate table A with prices from table B joining on Id. Sometimes table B doesn't have prices.
In cases were b doesn't have price I want to update the price to be another price from that same group, as I can't have a price of zero.
Is there an way to update table a price column using itself based on group? e.g. update productId 3 price to be the price of another product in it's group (1 or 2)
TABLE A after update
Productid price groupId
1 100 A
2 99 A
3 100 A
4 50 B
5 49 B
6 49 B
It seems silly but these are the business rules (it makes sense irl I simplified the problem for the example)
When I tried the following I got Error:
update 'Table A' t1
join (select price ,groupId from 'table A' where Price > 0 group by
groupId) as t2
on t1.groupId = t2.GroupId
SET t1.Price = t2.Price
(conn=58292) Can't reopen table: 'Table A'
I've thought of creating a third temporary table but that seems.... wrong? I am sure there must be a way to do this using update statement and joins
I would phrase the query as:
update tablea a
inner join (select groupId, max(price) price from tablea group by groupId) a1
on a1.groupId = a.groupId
set a.price = a1.price
where a.price = 0 and a1.price > 0
Notes:
the table name should be surrounded with single quotes (those stand for literal strings) - if your table name really contains spaces, then use backticks for quoting (or better, yet, fix the table name!)
I changed the subquery to make it a valid aggregation query - yours has non-aggregated columns that do not belong to the group by clause, which is not a good practice, and might generate errors, depending on the SQL mode of your database
In this demo on DB Fiddlde with your sample data, the content of the table after update is:
Productid | price | groupId
--------: | ----: | :------
1 | 100 | A
2 | 99 | A
3 | 100 | A
4 | 50 | B
5 | 49 | B
6 | 50 | B
my table:
id | item_id
1 | 5
2 | 5
3 | 7
4 | 2
sql:
$countWeek = $conn->query("SELECT count(item_id) FROM `myTable` GROUP BY `item_id`")->fetchColumn();
As you can see i have 2 duplicated rows with item_id = 5 i want to group these duplicated rows and output 3 rows on the count, but when i do echo $countWeek it output 1, why?
When i change the above sql to:
$countWeek = $conn->query("SELECT item_id FROM `myTable` GROUP BY `item_id`")->rowCount();
It returns the correct value, but i don't want to use rowCount() because i only need to count the rows and fetchColumn() with count() is far better in terms of speed.
You could use counct(distinct item_id)
SELECT count(distinct item_id)
FROM `myTable`
So I have a student_profiles table and ranks table, I want to get the next rank based on the student rank. For example, I have rank 5 then the next rank will be rank 6. So this is my rank structure.
RANKS TABLE:
SELECT * FROM RANKS WHERE style_id = 1"
id style_id level name type primary_colour secondary_colour
1 1 1 Newbie double #4e90b2 #3aad04
22 1 2 Normal solid #fba729 NULL
31 1 3 Expert solid #4e805b NULL
and this is STUDENT_PROFILES TABLE
id | student_id | rank_id
------------------------------------
1 | 1 | 36
2 | 4 | 22
3 | 7 | 10
so all I have a variable is student_id, rank_id & style_id
so for example, I have this value student_id = 4, rank_id = 22 & style_id = 1
It should return
id style_id level name type primary_colour secondary_colour
31 | 1 | 3 | Expert | Solid | #4e805b | NULL
If you just want to get the second row:
Do it like this:
select * from
(select * from table order by id asc limit 2) as a order by id desc limit 1
Any query structure it will work as you need second row if you follow that script.
Try with that:
SELECT * FROM `ranks` WHERE `level` > (SELECT `level` FROM `ranks` WHERE `id` = rank_id) LIMIT 1
But I think it isn't very effective solution.
One option for getting the next highest level in the RANKS table is to self-join this table on the level column, order ascending, and retain the very first record only.
SELECT r2.*
FROM RANKS r1
INNER JOIN
STUDENT_PROFILES s1
ON r1.id = s1.rank_id
INNER JOIN
RANKS r2
ON r2.level > r1.level
ORDER BY r2.level
LIMIT 1
Demo here:
SQLFiddle
Note: If RANKS has duplicate levels, and you want the next level with regard to cardinality (i.e. you don't want a duplicate equal level returned), then my query could be slightly modified to filter out such duplicates.
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
I have a table like this :
Type | Time
1 | 234234
2 | 234235
1 | 234238
3 | 234239
4 | 234240
1 | 234242
2 | 234245
I want to count number of all those rows where type=1 and next row's type=2.
For ex : The result here is 2.
I don't know how to put where clause on next row.
You should be able to implement user defined variables to get the total:
select count(*) Total
from
(
select type,
#row:=(case when #prev=1 and type=2 then 'Y' else 'N' end) as Seq,
#prev:=type
from yourtable, (SELECT #row:=null, #prev:=null) r
order by time, type
) src
where Seq = 'Y'
See SQL Fiddle with Demo