Delete records based on another table and criteria - ms-access

I'm using MS Access and I would like to delete some records from a table A based on another Table B and some criteria related to dates
I worked out a query in MS Access but this one does not really work.
DELETE [30 - Réception].*
FROM [30 - Réception] INNER JOIN [00 - TableOfDelivery] ON [00 - TableOfDelivery].item=[30 - Réception].item
WHERE [30 - Réception].[reception date] < (select min([Delivery date]) from [00 - TableOfDelivery] where [00 - TableOfDelivery].item=[30 - Réception].item) and [30 - Réception].[reception date] > (select max([Delivery date]) from [00 - TableOfDelivery] where [00 - TableOfDelivery].item=[30 - Réception].item);
I'd like to be able to delete records based on another table and criteria related to dates

Related

MySQL calculate yoy (year-over-year) data

I have some MAU data with monthly granularity like following:
I want to get yoy date like:
2016-04 yoy MAU = (2016-04 MAU - 2015-04 MAU)/2015-04 MAU
2016-03 yoy MAU = (2016-03 MAU - 2015-03 MAU)/2015-03 MAU
...
I am using MySQL so I don't have window function.
Is there any easier way to achieve what I want?
*The data type:
Period | varchar(16)
MAU | double
Ideally, periodic data would be stored as a date or as its components, in this case, year and month as separate integer columns. Since they are represented together as a string here, we need to parse them using SUBSTRING. The general idea behind the solution is that we need to join the table to itself using an ON clause that "lines up" each row with it's counterpart from one year prior.
This ought to do the trick:
select a.Period, a.MAU, b.Period as prior_year, b.MAU as prior_mau,
(a.MAU - b.MAU) / b.MAU as yoy
from tbl1 a
left join tbl1 b on
cast(substring(b.Period, 1, 4) as int) =
cast(substring(a.Period, 1, 4) as int) - 1
and substring(b.Period, 5, 3) = substring(a.Period, 5, 3)
order by a.Period asc
Here's a second way that's slightly less clear to read but is more efficient (especially if speed is an issue, the table is large, and it's indexed on Period) because it avoids a calculation in the where clause (at least on one side):
select a.Period, a.MAU, b.Period as prior_year, b.MAU as prior_mau,
(a.MAU - b.MAU) / b.MAU as yoy
from tbl1 a
left join tbl1 b on
a.Period
= cast(cast(substring(b.Period, 1, 4) as int) - 1 as varchar(4))
+ substring(b.Period, 5, 3)
order by a.Period asc
I hope this helps.

MYSQL updating a table containing a join and subquery

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").

SQL Deleting data based on max value of column

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)

How to select the field's increment from mysql

I have a table recording the accumulative total visit numbers of some web pages every day. I want to fetch the real visit numbers in a specific day for all these pages. the table is like
- record_id page_id date addup_number
- 1 1 2012-9-20 2110
- 2 2 2012-9-20 1160
- ... ... ... ...
- n 1 2012-9-21 2543
- n+1 2 2012-9-21 1784
the result I'd like to fetch is like:
- page_id date increment_num(the real visit numbers on this date)
- 1 2012-9-21 X
- 2 2012-9-21 X
- ... ... ...
- N 2012-9-21 X
but I don't want to do this in php, cause it's time consuming. Can I get what I want with SQL directives or with some mysql functions?
Ok. You need to join the table on itself by joining on the date column and adding a day to one side of the join.
Assuming:
date column is a legitimate DATE Type and not a string
Every day is accounted for each page (no gaps)
addup_number is an INT of some type (BIGINT, INT, SMALLINT, etc...)
table_name is substituted for your actual table name which you don't indicate
Only one record per day for each page... i.e. no pages have multiple counts on the same day
You can do this:
SELECT t2.page_id, t2.date, t2.addup_number - t1.addup_number AS increment_num
FROM table_name t1
JOIN table_name t2 ON t1.date + INTERVAL 1 DAY = t2.date
WHERE t1.page_id = t2.page_id
One thing to note is if this is a huge table and date is an indexed column, you'll suffer on the join by having to transform it by adding a day in the ON clause, but you'll get your data.
UPDATED:
SELECT today.page_id, today.date, (today.addup_number - yesterday.addup_number) as increment
FROM myvisits_table today, myvisits_table yesterday
WHERE today.page_id = yesterday.page_id
AND today.date='2012-9-21'
AND yesterday.date='2012-9-20'
GROUP BY today.page_id, today.date, yesterday.page_id, yesterday.date
ORDER BY page_id
Something like this:
SELECT date, SUM(addup_number)
FROM your_table
GROUP BY date

Postgres View / Function

I am trying to create a view which joins 2 tables but the results are dependent on the query. Here is a example of what I want to achieve.
I have a table called sessionaccounting and a table called sessionaccountingdailysplit.
sessionaccounting contains all our accounting data and sessionaccountingdailysplit is the sessionaccounting data split by date. They are joined by the foreign key sessionaccountingid
How the two tables work in unison is as follows:
for the row in sessionaccounting :
starttime - '2012-01-01', endtime - '2012-01-03', usage - 10000
for the rows in sessionaccountingdailysplit :
date - '2012-01-01', usage - 3000
date - '2012-01-02', usage - 5000
date - '2012-01-03', usage - 2000
Now what I want to do is if I run a view called vw_sessionaccounting as
SELECT *
FROM vw_sessionaccounting
WHERE starttime >= '2011-01-01' AND starttime <= '2011-01-02';
it must only sum the first two dates from sessionaccountingdailysplit and replace the usage in sessionaccounting accordingly for each effected row. (most cases sessionaccountingdailysplit wont have a row as there was no split)
So as above if I run
SELECT *
FROM sessionaccounting
WHERE starttime >= '2011-01-01' AND starttime <= '2011-01-02';
I will get the result of
starttime - '2012-01-01', endtime - '2012-01-03', usage - 10000
but if I run the query
SELECT *
FROM vw_sessionaccounting
WHERE starttime >= '2011-01-01'
AND starttime <= '2011-01-02';
I will get the result of
starttime - '2012-01-01', endtime - '2012-01-03', usage - 8000
Your question is a bit vague in several respects. But from what I gather and guess, your query (view) could look like this:
SELECT s.starttime
,s.endtime
,COALESCE(max(sd.date), s.endtime) AS effective_endtime_max_2_days
,COALESCE(sum(sd.usage), s.usage) AS usage_max_2_days
FROM sessionaccounting s
LEFT JOIN sessionaccountingdailysplit sd USING (sessionaccountingid)
WHERE sd.sessionaccountingid IS NULL -- no split ..
OR (starttime + 2) > sd.date -- .. or only the first two days of the split
GROUP BY s.starttime, s.endtime
Major points
Use a LEFT JOIN because:
... most cases sessionaccountingdailysplit wont have a row as there was no split
Only include the first two days: (starttime + 2) > sd.date
Be sure to include sessions without spit: WHERE sd.sessionaccountingid IS NULL OR
Use table aliases to get your monstrous table names out of the way:
FROM sessionaccounting s
sum() the usage for the first two days. If there was no spit take the original total usage instead: COALESCE(sum(sd.usage), s.usage) AS usage_max_2_days