I am looking to delete data from a table based on the max value of an index column - 23. Error received is 'In valid use of group function'
Currently Have:
DELETE FROM Raw_Data
WHERE
Raw_Data.Date_Index > MAX(`Date_Index`) - 23
Thanks
You can use JOIN:
DELETE rd
FROM Raw_Data rd CROSS JOIN
(SELECT MAX(Date_Index) as maxdi FROM Raw_data) m
WHERE rd.Date_Index > maxdi - interval 23 days;
Note: This uses CROSS JOIN. You can put the condition in an ON clause instead of a WHERE clause. I'm leaving it in this format because it more closely matches the query in the question.
DELETE FROM Raw_Data
WHERE
Raw_Data.Date_Index > (Select MAX(Date_Index) - 23 from Raw_Data)
Related
I am relatively new to SQL, i am trying to update monthly salary based on employees working for a certain duration, the query displays the data using info from the person and employee table but it won't update, i keep getting a 'operand should contain 1 column' error? How would i go about displaying all the data and be able to update the monthly_salary column as well? Thanks.
UPDATE employee ep set monthly_salary = monthly_salary*1.15 = all(
SELECT p.person_id, p.name_first, p.name_last, ep.monthly_salary, ep.start_date, curdate() as today_date,
TIMESTAMPDIFF(month,ep.start_date,curdate()) as duration_months
FROM employee ep
INNER JOIN person p ON ep.person_id = p.person_id having duration_months > 24);
query result
I want this expected result but the monthly salary hasn't been updated yet, is it possible to display this and update the monthly_salary?
You are not able to do both in a single query. Typically one would run a "select query" to inspect if the desired logic appears correct, e.g.
SELECT
p.person_id
, p.name_first
, p.name_last
, ep.start_date
, curdate() as today_date
, TIMESTAMPDIFF(month,ep.start_date,curdate()) as duration_months
FROM employee ep
INNER JOIN person p ON ep.person_id = p.person_id
WHERE ep.start_date < curdate() - INTERVAL 24 MONTH
;
In that query the important piece of logic is the where clause which seeks out any employees with a start date earlier than today - 24 months.
If that logic is correct, then apply the same logic in an "update query":
UPDATE employee ep
SET monthly_salary = monthly_salary*1.15
WHERE ep.start_date < curdate() - INTERVAL 24 MONTH
;
Syntax notes:
you cannot string multiple conditions together using multiple equality operators (monthly_salary = monthly_salary*1.15 = all(...) there are 2 = signs in that
x = all() requires that all values returned by a subquery will equal x
the having clause is NOT just a substitute for a where clause. A having clause is designed for evaluating aggregated data e.g. having count(*) > 2
Finally, while it was inventive to use the having clause, what you were doing was gaining access to the alias 'duration_months', so you could simply have done this instead:
where TIMESTAMPDIFF(month,ep.start_date,curdate()) > 24
BUT this is not a good way to filter information because it requires running a function on every row of data before a decision can be reached. This has he effect of making queries slower. Compare that to the following:
WHERE ep.start_date < curdate() - INTERVAL 24 MONTH
ep.start_date is not affected by any function, and curdate() - INTERVAL 24 MONTH is just one calculation (not done every row). So this is much more efficient (also known as "sargable").
This query below selects all rows that have a row with the same father registering 335 days or less since earlier registration. Is there a way to edit this query so that it does not eliminate the duplicate row in the output? I need to see all instances of the registration for that father within 335 days of each other.
SELECT * FROM ymca_reg a later
WHERE NOT EXISTS (
SELECT 1 FROM ymca_reg a earlier
WHERE
earlier.Father_First_Name = later.Father_First_Name
AND earlier.Father_Last_Name = later.Father_Last_Name
AND (later.Date - earlier.Date < 335) AND (later.Date > earlier.Date)
My current query is:
SELECT ymca_reg.* FROM ymca_reg WHERE (((ymca_reg.Year) In (SELECT Year FROM ymca_reg As Tmp
GROUP BY Year, Father_Last_Name, Father_First_Name
HAVING Count(*)>1
And Father_Last_Name = ymca_reg.Father_Last_Name
And Father_First_Name = ymca_reg.Father_First_Name)))
ORDER BY ymca_reg.Year, ymca_reg.Father_Last_Name, ymca_reg.Father_First_Name
This query does return all the duplicates for review correctly, but it's terribly slow because it doesn't use a join and as soon as I add the date criteria it only returns the later row. Thanks.
I think you want something like this:
SELECT *
FROM ymca_reg later
WHERE EXISTS (SELECT 1
FROM ymca_reg earlier
WHERE earlier.Father_First_Name = later.Father_First_Name AND
earlier.Father_Last_Name = later.Father_Last_Name AND
abs(later.Date - earlier.Date) < 335 and
later.Date <> earlier.Date
);
This should return all records that have such duplicates. Note that "later" and "earlier" are no longer really apt descriptions, but I left the names so you can see the similarity to your query.
Here is my table info,
__test
id points date
1 -50 30.09.2013
2 100 2.10.2013
3 100 3.10.2013
4 200 4.10.2013
From this i need to select records,if any of the value contains minus points based on the date
For ex:
select *
from #__test
where date between 30.09.2013 to 3.10.2013
Mentioned query is common for getting in between records fro two dates.But i need the records between two dates,if any of the value contains minus points.
How can i do this ? Kindly help me.
I think this is what you are after:
SELECT *
FROM #__test t
WHERE t.Date BETWEEN '20130930' AND '20131003'
AND EXISTS
( SELECT 1
FROM #__test t2
WHERE t2.Date BETWEEN '20130930' AND '20131003'
AND t2.points < 0
);
It simply checks for the existance of a negative value in the date range and then returns all records for that date range if one is found.
N.B This article is probably worth a read regarding using BETWEEN for date ranges, and there is further reading on date range queries in another article written by Aaron Bertrand
I try to make a simple query, spent on it a tone of hours and get nothing....
All I need is to get MAX date and all is corresponding fields.
I'm explain:
I have a table with this fields: BasketID, OrderStatusTypeID, StatusDate.
I try to get only one record that contain OrderStatusTypeID value with the last StatusDate.
This is the data
BasketID OrderStatusTypeID date
1111 13 2013-04-01 11:38:31
1111 26 2013-04-04 17:44:17
1111 39 2013-04-02 12:35:07
1111 40 2013-04-08 12:52:55
This is my query:
SELECT BasketID, OrderStatusTypeID, max(StatusDate) date
FROM st
where BasketID=1111
group by BasketID
This is the results i need
BasketID OrderStatusTypeID date
63558 40 2013-04-08 12:52:55
For some reason I only get OrderStatusTypeID = 13 and not 40!
(max of StatusDate, and NOT max of OrderStatusTypeID).
Why???
BasketID OrderStatusTypeID date
63558 13 2013-04-08 12:52:55
Thanks for fast response!
I assume you are using MySQL because you can run the query even if you have not specified all the non-aggregate column in the GROUP BY clause.
There are many ways to solve the problem but I'm used to do it this way. The query uses a subquery which separately gets the latest date for every BasketID. Since the subquery returned only two columns, you need to join it back on the table itself to get the other columns provided that it match on two columns: BasketID, Date.
SELECT a.*
FROM st a
INNER JOIN
(
SELECT BasketID, MAX(Date) max_date
FROM st
GROUP BY BasketID
) b ON a.BasketID = b.BasketID AND
a.Date = b.max_date
Your query has executed successfully without throwing an exception even though there are non-aggregate columns that are not specified in the GROUP BY clause because it is permitted in MySQL. See MySQL Extensions to GROUP BY.
I know this is an old thread, but
why isn't it possible to use ORDER BY and LIMIT in this case?
A query like that:
SELECT * FROM st
WHERE BasketID=1111
ORDER BY Date DESC
LIMIT 1
Its pretty easy to use TOP command like:
SELECT TOP 1 * FROM st
WHERE BasketID = 1111
ORDER BY date DESC
I want to get the data between a date. Am having some record with from and to date. Now i want to check that record using a date.
Employee Leave_from_date Leave_to_date Leave_Type
001 06-10-2012 07-10-2012 Casual
I want use the select statement like this
Select * from leave_request where fldempid=001 as L on fldfromdate
>= 06-10-2012 and fldtodate<='06-10-2012'
if am using 07-10-2012 means the above record displayed again.
Please help me to create this...
Reverse the usual position of values and columns in a between clause:
select *
from leave_request
where fldempid = 001
and '06-10-2012' between fldfromdate and fldtodate
try this one:
SELECT Employee, Leave_from_date, Leave_to_date, Leave_Type
FROM leave_request
WHERE fldempid = 001 AND
DATE('06-10-2012') between fldfromdate and fldtodate
I would suggest to convert the dates over to unix timestamps first so you can safely compare using the <= >= operators
e.g
SELECT
Employee, Leave_Type
UNIX_TIMESTAMP(fldfromdate) AS Leave_from_date,
UNIX_TIMESTAMP(fldtodate) as Leave_to_date
FROM
leave_request
where
fldempid=001 as L on
Leave_from_date>=1349481600 and Leave_to_date<=1349481600;
Haven't tried the above but should work with some tweeking...