I have written the following query to get the value with the max issue_id. But I get the issue_id 14 for book_id 2. What I want is to get issue_id 16 when book_id is 2. And issue_id 15 when book_id is 3 and so on.
SELECT issue.issue_id AS issue_id, issue.issue_date, issue.student_id, books.availability,
CASE WHEN NOW() > DATE_ADD(issue.issue_date, INTERVAL 20 DAY)
THEN 10*DATEDIFF(NOW(), DATE_ADD(issue.issue_date, INTERVAL 20 DAY))
ELSE 0 END AS fine_amount
FROM issue
INNER JOIN books
ON issue.book_id=books.book_id
WHERE books.book_id=2
HAVING MAX(issue.issue_id)
Use the ORDER BY .. LIMIT 1 to get the highest value
SELECT issue.issue_id AS issue_id, issue.issue_date, issue.student_id, books.availability,
CASE WHEN NOW() > DATE_ADD(issue.issue_date, INTERVAL 20 DAY)
THEN 10*DATEDIFF(NOW(), DATE_ADD(issue.issue_date, INTERVAL 20 DAY))
ELSE 0 END AS fine_amount
FROM issue
INNER JOIN books
ON issue.book_id=books.book_id
WHERE books.book_id=2
ORDER BY issue.issue_id DESC LIMIT 1
Related
I have a certain problem while trying to make an SQL. I have a table with the following format and data.
id
value
date
12
3
2020-06-01
12
4
2020-06-09
12
1
2020-06-20
5
4
2020-06-11
5
5
2020-06-17
My goal is to make something like that:
id
lower
higher
12
1
1
5
0
1
This looks for the value of the oldest row IN specific interval (ex. 100 days)and it compares it with all dates after that if their values are higher and lower and return the count.
I do have something that works but it requires more queries:
One to group take all ids with dates in the interval of xx days
SELECT id FROM table
WHERE date >= CURDATE() - INTERVAL 30 DAY GROUP BY id
ORDER BY id ASC;
And then I loop through each row and get its lower and higher values.
SELECT
*
FROM
(
SELECT
COUNT(*) AS higher, id
FROM
`table`
WHERE
id = 12 AND date > CURDATE() - INTERVAL 30 DAY AND value > (
SELECT value FROM table
WHERE table.date >= CURDATE() - INTERVAL 30 DAY AND id = 12
ORDER BY `table`.`date` ASC LIMIT 1
)
) AS t1,(
SELECT
COUNT(*) AS deteriorated_placements
FROM
`table`
WHERE
id = 12 AND date > CURDATE() - INTERVAL 30 DAY AND value < (
SELECT value FROM table
WHERE table.date >= CURDATE() - INTERVAL 30 DAY AND id = 12
ORDER BY `table`.`date` ASC LIMIT 1
)
) AS t2;
The problem with that is that I do around 40 more queries. I know it maybe is not a big issue but
Is there a way to somehow combine those 2 queries?
Use first_value():
select id,
sum(value < value_1) as lower,
sum(value > value_1) as higher
from (select t.*,
first_value(value) over (partition by id order by date) as value_1
from t
) t
group by id;
Date Range is last seven days. currently i am getting this data from this query
counts dates
1 2018-12-25
1 2018-12-26
3 2018-12-30
query is
select COALESCE(Count(campaign_id), 0) as counts,date(start_date) as dates from campaigns where segment_id=30
and date(start_date) BETWEEN DATE_SUB(CURDATE(),INTERVAL 7 DAY) AND CURDATE()
group by date(start_date)
but i want expected output is
counts dates
0 2018-12-24
1 2018-12-25
1 2018-12-26
0 2018-12-27
0 2018-12-28
0 2018-12-29
3 2018-12-30
You can generate 7 rows by using information_schema's views such as information_schema.tables
select (select count(*)
from campaigns
where start_date = e.dates
) count,
e.dates
from
(
select *
from campaigns c
right join
(
SELECT #cr := #cr + 1 as rn,
date_sub(curdate(), interval 7 - #cr day) as dates
from information_schema.tables c1
cross join (SELECT #cr := 0, #segID := 30) r
where #cr<7
) d on c.campaign_id = d.rn
where coalesce(c.segment_id,#segID) = #segID
) e;
count dates
0 24.12.2018
1 25.12.2018
1 26.12.2018
0 27.12.2018
0 28.12.2018
0 29.12.2018
3 30.12.2018
Rextester Demo
You need a way of generating all the dates. The standard answer is to use a left join and a calendar table or other table with the dates you want.
In your case, your table may already have the all the dates. If so, the simplest method is conditional aggregation:
select date(start_date) as dates,
sum(segment_id = 30) cnt_30
from campaigns
where start_date >= date_sub(curdate(), interval 7 day) and
start_date < date_add(curdate(), interval 1 day)
group by date(start_date);
You'll notice that I also modified the where clause, by removing the function calls on start_date. This allows the MySQL optimizer to use an index, if one is available.
I have a MySQL table with 2 fields: id_type and created_at
There are several rows with the same id_type and different timestamps. Eg:
3 - 2015-06-10 12:01:20
1 - 2015-03-21 04:14:10
1 - 2015-03-17 04:14:10
0 - 2015-05-06 21:43:00
3 - 2015-05-13 19:34:32
3 - 2015-07-18 03:47:55
I need to select id_type if the newest corresponding created_at is older than 30 days (Or in other words, any id_type that was last recorded more than 30 days ago)
Expected result:
1
0
I've tried:
SELECT id_type FROM table WHERE MAX(created_at) < DATE_SUB(NOW(), INTERVAL 30 day)
Which has given me the error:
invalid use of group function
How should I build it properly?
Try this,
SELECT id_type FROM table_b WHERE created_at IN (Select MAX(created_at) from table_b where created_at < DATE_SUB(NOW(), INTERVAL 30 day));
You can use this :
select id_type from `table` where `created_at` >= DATE_SUB(CURDATE(), INTERVAL 3 MONTH)
I have the following table:
user_id post_streak streak_date streak first_name club_id
-------- ----------- ------------ --------- ----------- --------
18941684 1 2015-05-05 15:36:18 3 user 1000
I want to change streak to 0 if it has been longer then 12 days.
current query:
select
first_name, streak, user_id from myTable
where
club_id = 1000
and
post_streak = 1
and
streak_date between date_sub(now(),INTERVAL 12 DAY) and now()
order by streak desc;
Which doesn't show results older then 12 days. I want to show all results but change "streak" to 0 if it has been longer the 12 days.
What is the best way to go about this?
UPDATE table
SET (streak)
VALUES (0)
WHERE streak_date < DATEADD(DAY, -12, NOW() );
SELECT first_name, streak, user_id from myTable
WHERE
club_id = 1000
AND
post_streak = 1
ORDER BY streak DESC;
First query will set all streak values to 0 for records that have streak_date of more than 12 days ago
Second query will get a list of all your records that have a club_id of 1000 and a post_streak of 1
Put the condition in the select, rather than the where:
select first_name,
(case when streak_date between date_sub(now(), INTERVAL 12 DAY) and now()
then streak
else 0
end) as streak,
user_id from myTable
where club_id = 1000
order by streak desc;
I'm not sure if the post_streak condition is needed in the where clause.
http://sqlfiddle.com/#!9/d8bbd/6
select
user_id,
first_name,
streak_date,
IF(streak_date between date_sub(now(),INTERVAL 12 DAY) and now(),streak,0)
from myTable
where
club_id = 1000
and
post_streak = 1
order by streak desc;
I'm trying to assign a value for events based on it's age using this:
SELECT u.iduser, timeIsImportant
FROM user AS u
LEFT OUTER JOIN(
SELECT action, user_id, action_time,
(IF(bb.action_time < DATE_SUB(CURDATE(), INTERVAL 7 DAY),
(CASE
WHEN bb.action_time BETWEEN DATE_SUB(CURDATE(), INTERVAL 3 MONTH) AND CURDATE() THEN 0.1
WHEN bb.action_time BETWEEN DATE_SUB(CURDATE(), INTERVAL 6 MONTH) AND CURDATE() THEN 0.2
WHEN bb.action_time BETWEEN DATE_SUB(CURDATE(), INTERVAL 12 MONTH) AND CURDATE() THEN 0.4
WHEN bb.action_time BETWEEN DATE_SUB(CURDATE(), INTERVAL 18 MONTH) AND CURDATE() THEN 0.7
WHEN bb.action_time BETWEEN DATE_SUB(CURDATE(), INTERVAL 24 MONTH) AND CURDATE() THEN 1.0
END), 0))
AS timeIsImportant
FROM bigbrother AS bb
ORDER BY bigbrother.uid DESC LIMIT 1)
AS bbb
ON
bbb.user_id = u.iduser AND bbb.action = "C"
WHERE u.iduser = 2;
The idea is that older 'events' on the bigbrother table need to subtract different values from a ranking query calculation. The timeIsImportant value from the query above, would be the agePoints on the following example.
sample data:
row1 row2
------------- -------------
rank: 4.7 rank 4.9
agePoints: 0.1 agePoints 0.4
timedRank: (rank-AgePoints) timedRank: (rank-AgePoints)
-------------------------------------------------------------
SQL: ORDER BY timedRank DESC
row1, row2
SQL: ORDER BY timedRank ASC
row2, row1
I wonder if there's another way to assign the values based on events age, since I'm doing this calculation on every page load in order to rank search results and found that this piece of code slows the overall performance when nested within the search query.