SQL query from time_in column but not from time_out column - mysql

I'm using mysql. I have a table time_record. There are four columns namely id, time_in, time_out and students_id. I only want to query the record of the latest time_in of the student but if the latest record of the student is in time_out, it will not query. How do I query the student's latest time_in record if given that the student still does not times out?
Thanks
Here is my sample code (though it returns both records from timein and timeout)
select concat (
st.student_fname,
' ',
st.student_lname
) as 'Name',
t.students_id,
t.time_in,
t.time_out,
case
when t.time_in > t.time_out
then t.time_in
else t.time_out
end as MostRecentDate
from classes c
join student_classes s on c.id = s.classes_id
join timerecords t on t.students_id = s.students_id
join students st on s.students_id = st.student_id
where c.employees_id = 'sessionvalue2'
and
where date (t.time_in) between date (now()) and date (now())

From what I understand, you want to query all results in which time_in is the latest entry and exclude results where time_out is the latest entry.
Try this:
SELECT DISTINCT(tr.id), tr.time_in
FROM time_record tr
WHERE tr.time_in > tr.time_out
ORDER BY tr.time_in DESC

I think your time_out columns may have nulls due to which the comparison results in false in that case and it return time_out.
Also,
date (t.time_in) between date (now()) and date (now())
doesn't make any sense. If you want to check the time_in for today's date, do:
date(t.time_in) = curdate();
Use curdate() instead of date(now()).
or Sargable so that index can be used if any:
date >= curdate()
and date < date_add(curdate(), interval 1 day)
Try flipping the condition like this:
select concat (
st.student_fname,
' ',
st.student_lname
) as 'Name',
t.students_id,
t.time_in,
t.time_out,
case
when t.time_in < t.time_out
then t.time_out
else t.time_in
end as MostRecentDate
from classes c
join student_classes s on c.id = s.classes_id
join timerecords t on t.students_id = s.students_id
join students st on s.students_id = st.student_id
where c.employees_id = 'sessionvalue2'
and date >= curdate()
and date < date_add(curdate(), interval 1 day)

Related

SUM subquery with condition depends on parent query columns returns NULL

everyone!
I'm trying to calc sum of price of deals by each day. What i do:
SET #symbols_set = "A,B,C,D";
DROP TABLE IF EXISTS temp_deals;
CREATE TABLE temp_deals AS SELECT Deal, TimeMsc, Price, VolumeExt, Symbol FROM deals WHERE TimeMsc >= "2019-04-01" AND TimeMsc <= "2019-06-30" AND FIND_IN_SET(Symbol, #symbols_set) > 0;
SELECT
DATE_FORMAT(TimeMsc, "%d/%m/%Y") AS Date,
Symbol,
(SELECT SUM(Price) FROM temp_deals dap WHERE dap.TimeMsc BETWEEN Date AND Date + INTERVAL 1 DAY AND dap.Symbol = Symbol) AS AvgPrice
FROM temp_deals
ORDER BY Date;
DROP TABLE IF EXISTS temp_deals;
But in result i've got NULL in AvgPrice column. I can't understand what i'm doing wrong.
It's look like i can't pass parent query's column to subquery, am i right?
Qualify your column names. But mostly, don't use a string for comparing dates:
SELECT DATE_FORMAT(d.TimeMsc, '%d/%m/%Y') AS Date,
d.Symbol,
(SELECT SUM(dap.Price)
FROM temp_deals dap
WHERE dap.TimeMsc >= d.TimeMsc AND
dap.TimeMsc < d.TimeMsc + INTERVAL 2 DAY AND -- not sure if you want 1 day or 2 day
dap.Symbol = d.Symbol
) AS AvgPrice
FROM temp_deals d
ORDER BY d.TimeMsc;

mysql how to mulitply some values in the same column but not others if it meets a condition

Is it possible to mulitply some values in the same column but not others if the value meets a certain condition? I don't want to create another column.
Query I am working with:
SELECT
name ,
ROUND(SUM(orderline_sales.amount * orderline_sales.price) * orders_sales.discount * customers.annual_discount) AS total_revenue
FROM
orderline_sales
JOIN
orders_sales ON orders_sales.id = orderline_sales.orders_sales_id
JOIN
employee ON orders_sales.empoyee_id = employee.id
JOIN
customers ON orders_sales.customer_id = customers.id
WHERE
date BETWEEN DATE_SUB(CURRENT_DATE, INTERVAL 365 DAY) AND CURRENT_DATE
GROUP BY employee.name
ORDER BY totale_omzet DESC
LIMIT 1;
The orders_sales table contains a date attributetype and the orders_sales table has a 1:n cardinal relationship with orderline_sales. I only want to multiply the SUM result with customers.annual_discount if the YEAR of the order is higher than 2017. How would I go about doing this?
you can use CASE.
SELECT
CASE WHEN YEAR > 2017 THEN
ROUND(SUM(orderline_sales.amount * orderline_sales.price) *
orders_sales.discount *
customers.annual_discount)
ELSE
(orderline_sales.price * orders_sales.discount * customers.annual_discount)
END AS total_revenue FROM orderline_sales
JOIN
orders_sales ON orders_sales.id = orderline_sales.orders_sales_id
JOIN
employee ON orders_sales.empoyee_id = employee.id
JOIN
customers ON orders_sales.customer_id = customers.id
WHERE
date BETWEEN DATE_SUB(CURRENT_DATE, INTERVAL 365 DAY) AND CURRENT_DATE
GROUP BY employee.name
ORDER BY totale_omzet DESC

How to get results not between two dates?

I have two dates that property has been blocked on that two days like start date 2017-01-20 and end end 2017-01-25. Between these two dates property has been blocked. When I search with these two dates except these two dates I want to get the remaining dates.
Here I have tried by searching the web in MySQL like
select `pd`.*, `pa`.*
from `property_details` as `pd` left join
`property_gallery` as `pg`
on `pg`.`property_id` = `pd`.`property_id` left join
`property_preblock_details` as `pbd`
on `pbd`.`property_id` = `pd`.`property_id` left join
`property_amenity` as `pa`
on `pa`.`property_id` = `pd`.`property_id`
where `pbd`.`start_date` >= '2017-01-20' and `pbd`.`end_date` <= '2017-01-25'
and
select pd.* from
`property_details` as `pd` left join
`property_gallery` as `pg` on `pg`.`property_id` = `pd`.`property_id`
left join `property_preblock_details` as `pbd`
on `pbd`.`property_id` = `pd`.`property_id`
left join `property_amenity` as `pa`
on `pa`.`property_id` = `pd`.`property_id`
where `pbd`.`start_date` NOT BETWEEN CAST('2017-01-20' AS DATE) and CAST('2017-01-25' AS DATE)
AND `pbd`.`end_date` NOT BETWEEN CAST('2017-01-20' AS DATE) and CAST('2017-01-25' AS DATE)
But I'm getting results as between dates.
I don't want to get between dates results, I want to get not between dates results.
Property_rate
id start_date end_date prop_id
1 2017-01-20 2017-01-25 1
2 2017-01-26 2017-01-27 1
3 2017-01-26 2017-01-28 2
Property
prop_id prop_name
1 test1
2 test2
If I select 2017-01-20 and 2017-01-25, I want to get 'test2' property details only. Not 'test1' details.
You've very close. Your query says this:
where `pbd`.`start_date` >= '2017-01-20' /* close, but wrong */
and `pbd`.`end_date` <= '2017-01-25'
What you want is this:
where ( `pbd`.`start_date` < '2017-01-20'
or `pbd`.`end_date` > '2017-01-25')
It can also be written
where not ( `pbd`.`start_date` >= '2017-01-20'
and `pbd`.`end_date` <= '2017-01-25')
BEWARE Your query may have another mistake in it. If your start_date and end_date columns have the DATE data type, you're all set. But if they have another data type, such as DATETIME or TIMESTAMP, your query has another problem. To catch all the rows with date/time values on the days 20-Jan-2017 -- 25-Jan-2017 you need this
where `pbd`.`start_date` >= '2017-01-20' /*dates IN range */
and `pbd`.`end_date` < '2017-01-26'
Notice I moved the desired end date one day later and used < instead of <=. This works correctly for
2017-01-25 23:59 should be in range
2017-01-26 00:00 should be out of range
2017-01-26 00:01 should be out of range
Try:
SELECT *
FROM `Table`
WHERE `DATECOLUMN` NOT
IN (
SELECT 'ID'
FROM `Table`
WHERE `DATECOLUMN`
BETWEEN (
'2017-02-10 00:00:00'
)
AND (
'2017-09-14 00:00:00'
)
)
LIMIT 0 , 30

Select depending CURDATE MySQL

I have the following query:
SELECT tbl_usuarios.Correo,
tbl_alertas.Id,
tbl_alertas.Purpose,
tbl_alertas.Status,
tbl_alertas.OpenDate,
tbl_alertas.CloseDate,
tbl_alertas.Owner,
tbl_alertas.ValueStream,
tbl_alertas.Family
FROM tbl_usuarios
INNER JOIN tbl_alertas ON tbl_usuarios.Nombre = tbl_alertas.Owner
WHERE (STATUS = 'En aprobacion' OR STATUS = 'Activa')
AND CloseDate < CURDATE()
As a result of this query I have the following table:
Everything it's ok.
Now, the problem is that I 'm going to use that query in my website, I create a JavaScript function which is going to be executed every 5th and every 19th of a month. My question, what can I do to only select the row which his CloseDate is <= yyyy-mm-07 or CloseDate >= yyyy-mm-07 and <= yyyy-mm-21 depending of CURDATE(5th or 19th), example:
Curdate = yyyy-mm-05.
Expected result: Data from Id 00003
What I tried was adding another AND to the query, something like this:
AND CloseDate < CURDATE() AND CloseDate <= '2016-09-07'
If my question is not much clear let me explain with this, I want to select CloseDate '2016-09-07' when curdate = '2016-whatever-05, 06', 07 or select CloseDate '2016-09-21' where curdate = '2016-whatever-19, 20, 21'.
Don't know if I understood your problem correctly but check the DAYOFMONTH() or simply DAY() function.
Returns the day of the month for date, in the range 1 to 31, or 0 for
dates such as '0000-00-00' or '2008-00-00' that have a zero day part.
You can use it like this
SELECT tbl_usuarios.Correo,
tbl_alertas.Id, tbl_alertas.Purpose,
tbl_alertas.Status, tbl_alertas.OpenDate,
tbl_alertas.CloseDate,
tbl_alertas.Owner,
tbl_alertas.ValueStream,
tbl_alertas.Family
FROM tbl_usuarios
INNER JOIN tbl_alertas
ON tbl_usuarios.Nombre = tbl_alertas.Owner
WHERE (STATUS = 'En aprobacion' OR STATUS = 'Activa')
AND (CASE
WHEN DAY(CURDATE()) = '5' AND DATE(CloseDate) <= DATE_FORMAT(NOW() ,'%Y-%m-07')
THEN 1
WHEN DAY(CURDATE()) = '19' AND (DATE(CloseDate) >= DATE_FORMAT(NOW() ,'%Y-%m-07') AND DATE(CloseDate) <= DATE_FORMAT(NOW() ,'%Y-%m-21'))
THEN 1
ELSE 0
END)

How to categorize customer through MYSQL query?

I am finding difficulty in writing mysql query to categorize my customers. I am categorizing customers based on number of hits on my website.like
New customer with one hits.
New customer with multiple hits.
Old customer
My Log table schema is as follows
Unique customer ID, Current Date, Subscribed, Hits Count
To categorize customer how can I compare current date customer logs with all the previous date logs through single query
It's not clear from your description, is customer_id unique?
Or is it the tuple (customer_id,current_date,subscribed,hits_count) that is unique?
If customer_id is unique, then something like this will return the specified result:
SELECT t.customer_id
, CASE
WHEN t.hits_count = 1 AND t.current_date = DATE(NOW())
THEN 'New customer with one hits.'
WHEN t.hits_count > 1 AND t.current_date = DATE(NOW())
THEN 'New customer with multiple hits.'
ELSE 'Old customer'
END AS category
FROM mytable t
If customer_id is not unique, then one way (but not the most efficient way) to get the specified result:
SELECT t.customer_id
, CASE
WHEN t.total_hits_count = 1 AND t.min_current_date = DATE(NOW())
THEN 'New customer with one hits.'
WHEN t.total_hits_count > 1 AND t.min_current_date = DATE(NOW())
THEN 'New customer with multiple hits.'
ELSE 'Old customer'
END AS category
FROM ( SELECT h.customer_id
, MIN(h.current_date) AS min_current_date
, SUM(h.hits_count) AS total_hits_count
FROM mytable h
GROUP BY h.customer_id
) t
The inline view aliased as t gets us unique values for customer_id, along with the earliest current_date, and the total of the hits_count. (You can run just the query inside the parens to verify it's returning the desired result.) The outer query is identical to the first query, with just some renamed columns.
The inline view isn't necessary, you could get an equivalent result (more efficiently) with something like this:
SELECT t.customer_id
, CASE
WHEN SUM(t.hits_count) = 1 AND MIN(t.current_date) = DATE(NOW())
THEN 'New customer with one hits.'
WHEN SUM(t.hits_count) > 1 AND MIN(t.current_date) = DATE(NOW())
THEN 'New customer with multiple hits.'
ELSE 'Old customer'
END AS category
FROM mytable t
GROUP BY t.customer_id
NOTE There's some corner cases that will cause customer_id to be categorized as 'Old customer', such as SUM(t.hits_count) < 1, or t.current_date IS NULL, etc.
To specifically test for a row with a current_date before today's date, make a specific test for that in the CASE expression:
SELECT t.customer_id
, CASE
WHEN SUM(t.hits_count) = 1 AND MIN(t.current_date) = DATE(NOW())
THEN 'New customer with one hits.'
WHEN SUM(t.hits_count) > 1 AND MIN(t.current_date) = DATE(NOW())
THEN 'New customer with multiple hits.'
WHEN MIN(t.current_date) < DATE(NOW())
THEN 'Old customer'
ELSE 'Some other category'
END AS category
FROM mytable t
GROUP BY t.customer_id
NOTE
I assumed that the current_date column was of type DATE, and not DATETIME or TIMESTAMP. If that column also includes a time component which is not equal to midnight 00:00:00, then the equality comparison to DATE(NOW()) is not going to return TRUE whenever that time component is not midnight.
In that case, we'd prefer to check a range of datetime values, replacing
... AND t.current_date = DATE(NOW())
with something like this:
... AND t.current_date >= DATE(NOW()) AND t.current_date < DATE(NOW()) + INTERVAL 1 DAY