Table: mytable
id created_on status purchase_price_without_tax purchase_tax
1 2015-08-07 00:00:00 1 3322.80 5.00
1 2015-07-15 15:16:23 7 3599.00 71.98
1 2015-07-14 15:16:23 2 3599.00 71.98
1 2015-07-16 15:16:23 4 3599.00 91.98
1 2015-07-17 15:16:23 5 3599.00 21.98
here is my query
SELECT * FROM mytable
WHERE
(IF( `status` IN('1','2') , (`status` IN('1','2')), (`status` IN('7')) ) )
AND id=1
But not getting proper result, because I would like it to be like this:
where
IF (`status`=1 OR `status`=2 )
then status IN ('1','2')
ELSE
`status`=7
Note : If status is 1 or 2 then it will left all other status row and select only those rows which have status 1 OR 2 . If there is no rows which have status as 1 or 2, then select only those rows which have status = 7
Use a UNION of two queries that test the two cases.
SELECT *
FROM mytable
WHERE status IN (1, 2)
AND EXISTS (SELECT 1 FROM mytable WHERE status IN (1, 2))
UNION
SELECT *
FROM mytable
WHERE status = 7
AND NOT EXISTS (SELECT 1 FROM mytable WHERE status IN (1, 2))
Related
I want select rows from my table with last status_Id if there is a row with status_Id = 2 for that rows
ticketStatus_Id ticket_Id status_Id
======================================
1 1 1
2 1 2 -
3 1 3 *
4 2 1
5 3 1
6 3 2 - *
7 4 1
8 4 2 -
9 4 3
10 4 4 *
I want select just rows 3, 6, 10. there are another rows with status_Id = 2 (rows 2, 6, 8) for that ticket_Id,
In other word How to select rows 3,6,10 with ticket_Id =1,3,4 that there are another row with these ticket_Ids and status_Id=2 (rows 2,6,8)
If you want the complete row, then I would view this as exists:
select t.*
from t
where exists (select 1
from t t2
where t2.ticket_id = t.ticket_id and t2.status_id = 2
) and
t.status_Id = (select max(t2.status_id)
from t t2
where t2.ticket_id = t.ticket_id
);
If you just want the ticket_id and status_id (and not the whole row), I would recommend aggregation:
select ticket_id, max(status_id)
from t
group by ticket_id
having sum(status_id = 2) > 0;
In your case, ticketStatus_Id seems to increase with status_id, so you can use:
select max(ticketStatus_Id) as ticketStatus_Id, ticket_id, max(status_id) as Status_Id
from t
group by ticket_id
having sum(status_id = 2) > 0;
First, for each ticket we get the row with the highest status. We can do this with a self-join. Each row is joined with the row with the next highest status. We select the rows which have no higher status, those will be the highest. Here's a more detailed explanation.
select ts1.*
from ticket_statuses ts1
left outer join ticket_statuses ts2
on ts1.ticket_Id = ts2.ticket_Id
and ts1.status_Id < ts2.status_Id
where ts2.ticketStatus_Id is null
3 1 3
4 2 1
6 3 2
10 4 4
11 5 3
Note that I've added a curve-ball of 11, 5, 3 to ensure we only select tickets with a status of 2, not greater than 2.
Then we can use that as a CTE (or subquery if you're not using MySQL 8) and select only those tickets who have a status of 2.
with max_statuses as (
select ts1.*
from ticket_statuses ts1
left outer join ticket_statuses ts2
on ts1.ticket_Id = ts2.ticket_Id
and ts1.status_Id < ts2.status_Id
where ts2.ticketStatus_Id is null
)
select ms.*
from max_statuses ms
join ticket_statuses ts
on ms.ticket_id = ts.ticket_id
and ts.status_id = 2;
3 1 3
6 3 2
10 4 4
This approach ensures we select the complete rows with the highest statuses and any extra data they may contain.
dbfiddle
This is basicaly a "last row per group" problem. You will find some solutions here. My prefered solution would be:
select t.*
from (
select max(ticketStatus_Id) as ticketStatus_Id
from mytable
group by ticket_Id
) tmax
join mytable t using(ticketStatus_Id)
The difference in your question is that you have a condition requiring a specific value within the group. This can be solved with a JOIN within the subquery:
select t.*
from (
select max(t1.ticketStatus_Id) as ticketStatus_Id
from mytable t2
join mytable t1 using(ticket_Id)
where t2.status_Id = 2
group by t2.ticket_Id
) tmax
join mytable t using(ticketStatus_Id)
Result:
| ticketStatus_Id | ticket_Id | status_Id |
| --------------- | --------- | --------- |
| 3 | 1 | 3 |
| 6 | 3 | 2 |
| 10 | 4 | 4 |
View on DB Fiddle
A solution using window functions could be:
select ticketStatus_Id, ticket_Id, status_Id
from (
select *
, row_number() over (partition by ticket_Id order by ticketStatus_Id desc) as rn
, bit_or(status_Id = 2) over (partition by ticket_Id) > 0 as has_status2
from mytable
) x
where has_status2 and rn = 1
A quite expressive way is to use EXISTS and NOT EXISTS subquery conditions:
select t.*
from mytable t
where exists (
select *
from mytable t1
where t1.ticket_Id = t.ticket_Id
and t1.status_Id = 2
)
and not exists (
select *
from mytable t1
where t1.ticket_Id = t.ticket_Id
and t1.ticketStatus_Id > t.ticketStatus_Id
)
SELECT a.*
FROM t a
JOIN
(
SELECT ticket_id, MAX(status_id) max_status_id
FROM t
WHERE status_id >= 2
GROUP BY ticket_id
) b
ON a.ticket_id = b.ticket_id
AND a.status_id = b.max_status_id;
SELECT
MAX(m1.ticketstatus_Id) as ticket_status,
m1.ticket_Id as ticket,
MAX(m1.status_Id) as status
FROM mytable m1
WHERE
m1.ticket_Id in (select m2.ticket_Id from mytable m2 where m2.ticket_Id=m1.ticket_Id and m2.status_Id=2)
GROUP BY m1.ticket_Id
I have table 'printorders' :
id | faktor | status
1 | 326548768 | 6
2 | 657657875 | 5
and I have table 'delivery' :
id | faktorids
1 | 326548768-657657875
2 | 876876575-548548534
I want to select from delivery where faktors in faktorids all are equal to 6
and here is my query :
SELECT *,
(
SELECT status
FROM printorders
WHERE faktor = (SUBSTRING(faktorids, 1, 9))
LIMIT 1
) AS d1,
(
SELECT status
FROM printorders
WHERE faktor = (SUBSTRING(faktorids, 11, 9))
LIMIT 1
) AS d2
FROM delivery
WHERE d1= 6 AND d2 = 6
but it do not work for me, where is problem?
I want to select from delivery where faktors in faktorids all are
equal to 6
i assume you only want factor 326548768 because thats the only one with status 6?
I believe you want this query more or less but hard to say without expected results (query not tested).
SELECT
printorders__status__6.*
FROM (
SELECT
printorders.*
FROM
printorders
WHERE
printorders.status = 6
) AS printorders__status__6
INNER JOIN
delivery
ON
FIND_IN_SET(
printorders__status__6.faktor
, REPLACE(
delivery.faktorids
, '-'
, ','
)
)
First, you have an extra comma after d2
) AS d2,
FROM delivery
Also your phrase should look a little like this
select * from
(SELECT *,
(
SELECTstatus
FROM printorders
WHERE faktor = (SUBSTRING(faktorids, 1, 9)) AND status ='requested'
LIMIT 1
) AS d1,
(
SELECT status
FROM printorders
WHERE faktor = (SUBSTRING(faktorids, 11, 9))
LIMIT 1
) AS d2
FROM delivery) main
WHERE d1= 6 AND d2 = 6
I have two tables like below
Table 1 :
Id User_id rating1 rating2 rating3
1 4 4 3 5
2 4 5 2 2
3 1 5 5 5
4 4 1 2 3
Table 2 :
Id User rating1 rating2 rating3 comment
1 1 5 2 1 okay
2 4 2 4 4 good
I want to get the count of user_id who having rating1 value between 1 , 2 , 3, 4, 5 and who having rating2 value between 1 , 2 , 3, 4, 5 and who having rating3 value between 1 , 2 , 3, 4, 5
I am trying the following way ,
select count(Table1.User_id)
from Table1
join Table2
on Table1.User_id = Table2.User
where Table1.rating1 = ( 1 || 2 || 3 || 4 || 5)
and Table2.rating1 = ( 1 || 2 || 3 || 4 || 5 )
But it's not working.
based on your comment, your query is very far from your desire result.
You need to pivot your table to be a single column
SELECT rating, count(*)
FROM (
SELECT `User_id` , `rating1` as rating FROM Table1
UNION ALL
SELECT `User_id` , `rating2` as rating FROM Table1
UNION ALL
SELECT `User_id` , `rating3` as rating FROM Table1
UNION ALL
SELECT `User` , `rating1` as rating FROM Table2
UNION ALL
SELECT `User` , `rating2` as rating FROM Table2
UNION ALL
SELECT `User` , `rating3` as rating FROM Table2
) as combine
GROUP BY rating
ORDER BY rating
Use IN (1,2,3,4,5) Insted of = (1,2,3,4,5)
It will give error of multiple oprands since equal can be use when it comes to compare one on one value.
SELECT t1.user_id,t2.user,count(*) as Count_Rate
FROM
(SELECT * FROM table1 WHERE rating1 IN ('1','2','3','4','5')) as t1
JOIN
(SELECT * FROM table2 WHERE rating1 IN ('1','2','3','4','5')) as t2
on t1.user_id = t2.user
GROUP by user_id
Or You can try this also by adding,
(SELECT *,count(rating1='1') AS rate1 FROM table1 WHERE rating1 IN ('1','2','3','4','5')) as t1
table like this:
-----------------------------
id pid key value
-----------------------------
1 3 all 120
2 3 today 180
3 9 all 200
4 9 today 150
5 9 others 0
-----------------------------
how to
select * from table if all(120) < today(180) and if they have same pid(3)
I hope the result should be:
---------------------------
id pid key value
---------------------------
1 3 all 120
2 3 today 180
Assuming you want all entries for which another entry with all < today exists for the same pid
select t from table t where exists(
select * from table t2 where t.all < t2.today and t.pid = t2.pid
)
Try this:
select t1.*
from yourtable t1
inner join (
select *
from yourtable
group by pid
having sum(if(`key` = 'all', `value`, 0)) < sum(if(`key` = 'today', `value`, 0))
) t2 on t1.pid = t2.pid
SQLFiddle Demo
I have table:
id date default(bool)
1 2015-01-01 0
2 2015-01-02 0
3 2015-01-03 1
4 2015-01-04 1
5 2015-01-05 1
6 2015-01-06 0
7 2015-01-07 0
8 2015-01-08 1
9 2015-01-09 1
10 2015-01-10 0
I want only rows where ordered by date rows change default column from 0 to 1, so in this table rows: 3 and 8.
If id can be used instead of date, use a correlated sub-query to read previous row's value:
select *
from tablename t1
where default = 1
and (select default from tablename t2
where t2.id = t1.id - 1) = 0
Use date instead to find previous row:
select *
from tablename t1
where default = 1
and (select default from tablename t2
where t2.date = (select max(date) from tablename
where date < t1.date)) = 0
Here is another way using dynamic variable
select t.id,t.date,t.`default`
from (
select
t1.*,
#default := if(#prev_default = 0 and t1.`default` = 1,1,0) as def,
#prev_default:=t1.`default`
from (
select * from test order by date
)t1,
(select #prev_default:= 2,#default:=0)r
)t
where t.def = 1 ;