Problem with last record in ms access query - ms-access

I have 3 Access queries , The first query (Q0) filters a table to get specific data :
SELECT Table1.ID, Table1.Machine, Table1.Po, Table1.Priority, Table1.Zdate, Table1.Status
FROM Table1
WHERE (((Table1.Status)<>"Not Needed"));
The second query (Q1) Sorts the first query depending on multiple condition like date and priority :
SELECT Q0.Machine, Q0.Priority, Q0.Zdate, Q0.Po, Q0.ID, Q0.Status
FROM Q0
GROUP BY Q0.Machine, Q0.Priority, Q0.Zdate, Q0.Po, Q0.ID, Q0.Status
ORDER BY Q0.Machine, Q0.Priority DESC , Q0.Zdate;
The third query (Q2) :
SELECT Table2.MachineNumber, Last(Q1.Priority) AS LastOfPriority, Last(Q1.Zdate) AS LastOfZdate, Last(Q1.Po) AS LastOfPo, Last(Q1.ID) AS LastOfID, Last(Q1.Status) AS LastOfStatus
FROM Table2 LEFT JOIN Q1 ON Table2.MachineNumber = Q1.Machine
GROUP BY Table2.MachineNumber;
Q2 should get the last record for each machine number in the Q1 with the rest of data in the same record , So the priority should be all "1" with the right date , the right Po and the right status , Unfortunately it doesn’t happen and get the record with the last ID in each machine number .
The correct result should be like
Sorry For long question guys , Thanks in advance
Edit#1
I just need the last record from each machine number in Q1 no matter what condition because it is not always the latest date or the highest priority i need the Q2 to Strictly tied to the last record of each machine number

Don't use Last but Max:
SELECT Table2.MachineNumber, Max(Q1.Priority) AS HighPriority, Max(Q1.Zdate) As LatestDate, ... etc.

Related

How to combine rows and take highs and lows from those rows

I am trying to generate a 5M OHLC chart (Open, High, Low, Close). I'm currently reading in data by the minute, but I want to make a 5 minute data chart as well which I can do pretty easy by simply doing
SELECT * FROM intraday_data.intraday WHERE intraday.id mod 5 = 0;
However, this doesn't accurately represent the data because for the OHLC chart to be accurate it would need to also have the open from the very first row and close from the very last row, and it would have to have the highest high from all 5 and the lower low from all 5 if that makes sense, I would also like to implement where it is able to add up all of the volumes.
Here is the current schema:
As you can see the open in highlighted would need to be pulled out in the final row, the highlighted value in the 5th row which is the highest high as well as the remaining rows and the total volume, so essentially after running the function the row presented should be:
id 5: open 4402.75: high 4403: low 4402.5: volume : 12+24+37+32+29
Obviously, I would need to iterate over all of the rows and return every 5th row with the data combined from the last 5 rows,
Current Updated Query:
select open_close_t.cross_id,open_close_t.open_val,open_close_t.close_val,high_low_t.high,high_low_t.low,high_low_t.total_volume from (
select open_close.max_id as cross_id,open_t.open as open_val,close_t.close as close_val from
(select max(id) as max_id,min(id) as min_id from intraday group by FLOOR(id/5)) as open_close
inner join intraday as open_t on (open_t.id=open_close.min_id)
inner join intraday as close_t on (close_t.id=open_close.min_id)
) as open_close_t
left join (
select max(id) as cross_id,max(high_val) as high,min(low_val) as low,sum(volume) as total_volume
from (select id,GREATEST(open,high,low,close) as high_val,GREATEST(open,high,low,close) as low_val,volume from intraday_data.intraday) as _t
group by FLOOR(id/5)
) as high_low_t on (open_close_t.cross_id=high_low_t.cross_id)
Current Updated Results:
we can seperate this question with two main query.
get the the open and close value
get max and min id of every 5th row
use that max_id and min id to get close and open value
get highest and lowest value
first we need get max and min cross open,high,low,close per row
group by 5th rows the previous generated and get highest and lowest values
join two previous generated table by max_id(cross_id in the sql) of each 5th rows
select open_close_t.cross_id,open_close_t.open_val,open_close_t.close_val,high_low_t.high,high_low_t.low,high_low_t.total_volume from (
select open_close.max_id as cross_id,open_t.open as open_val,close_t.close as close_val from
(select max(id) as max_id,min(id) as min_id from intraday group by CEILING(id/5)) as open_close
inner join intraday as open_t on (open_t.id=open_close.min_id)
inner join intraday as close_t on (close_t.id=open_close.max_id)
) as open_close_t
left join (
select max(id) as cross_id,max(high_val) as high,min(low_val) as low,sum(volume) as total_volume
from (select id,greatest(open,high,low,close) as high_val,least(open,high,low,close) as low_val,volume from intraday) as _t
group by CEILING(id/5)
) as high_low_t on (open_close_t.cross_id=high_low_t.cross_id)
fix every 4 instead every 5 bug,because I should use ceiling not floor
the open_close temp table join problem from close_t.id=open_close.min_id to close_t.id=open_close.max_id
the lowest value using least not greatest
I made a db-fiddle example,if has further problem we can test on db-fiddle

SQL Capture duplicate records across two DIFFERENT columns

I am writing an Exception Catching Page using MySQL for catching duplicate billing entries the following scenario.
Items details are entered in a table which has the following two columns (among others).
ItemCode VARCHAR(50), BillEntryDate DATE
It often happens that same item's bill is entered multiple times, but over a period of few days. Like,
"Football","2019-01-02"
"Basketball","2019-01-02"
...
...
"Football","2019-01-05"
"Rugby","2019-01-05"
...
"Handball","2019-01-05"
"Rugby","2019-01-07"
"Rugby","2019-01-10"
In the above example, the item Football is billed twice - first on 2Jan and again on 5Jan. Similarly, item Rugby is billed thrice on 5,7,10Jan.
I am looking to write simple SQL which can pickup each item [say, using distinct(ItemCode) clause], and then display all the records which are duplicates over a period of 30 days.
In the above case, the expected output should be the following 5 records:
"Football","2019-01-02"
"Football","2019-01-05"
"Rugby","2019-01-05"
"Rugby","2019-01-07"
"Rugby","2019-01-10"
I am trying to run the following SQL:
select * from tablen a, tablen b, where a.ItemCode=b.ItemCode and a.BillEntryDate = b.BillEntryDate+30;
However, this seems to be highly inefficient as it is running for long without displaying any records.
Is there any possibility for getting a less complex and faster method?
I did explore existing topics (like How do I find duplicates across multiple columns?), but it is catching duplicates where BOTH columns have same value. My requirement is one column same value, and second column varying over a month-long date range.
You can use:
select t.*
from tablen t
where exists (select 1
from tablen t2
where t2.ItemCode = t.ItemCode and
t2.BillEntryDate <> t.BillEntryDate and
t2.BillEntryDate >= t1.BillEntryDate - interval 30 day and t2.BillEntryDate <= t1.BillEntryDate + interval 30 day
);
This will pick up both duplicates in the pair.
For performance, you want an index on (ItemCode, BillEntryDate).
With EXISTS:
select ItemCode, BillEntryDate
from tablename t
where exists (
select 1 from tablename
where
ItemCode = t.ItemCode
and
abs(datediff(BillEntryDate, t.BillEntryDate)) between 1 and 30
)

Can SQL query do this?

I have a table "audit" with a "description" column, a "record_id" column and a "record_date" column. I want to select only those records where the description matches one of two possible strings (say, LIKE "NEW%" OR LIKE "ARCH%") where the record_id in each of those two matches each other. I then need to calculate the difference in days between the record_date of each other.
For instance, my table may contain:
id description record_id record_date
1 New Sub 1000 04/14/13
2 Mod 1000 04/14/13
3 Archived 1000 04/15/13
4 New Sub 1001 04/13/13
I would want to select only rows 1 and 3 and then calculate the number of days between 4/15 and 4/14 to determine how long it took to go from New to Archived for that record (1000). Both a New and an Archived entry must be present for any record for it to be counted (I don't care about ones that haven't been archived). Does this make sense and is it possible to calculate this in a SQL query? I don't know much beyond basic SQL.
I am using MySQL Workbench to do this.
The following is untested, but it should work asuming that any given record_id can only show up once with "New Sub" and "Archived"
select n.id as new_id
,a.id as archive_id
,record_id
,n.record_date as new_date
,a.record_date as archive_date
,DateDiff(a.record_date, n.record_date) as days_between
from audit n
join audit a using(record_id)
where n.description = 'New Sub'
and a.description = 'Archieved';
I changed from OR to AND, because I thought you wanted only the nr of days between records that was actually archived.
My test was in SQL Server so the syntax might need to be tweaked slightly for your (especially the DATEDIFF function) but you can select from the same table twice, one side grabbing the 'new' and one grabbing the 'archived' then linking them by record_id...
SELECT
newsub.id,
newsub.description,
newsub.record_date,
arc.id,
arc.description,
arc.record_date,
DATEDIFF(day, newsub.record_date, arc.record_date) AS DaysBetween
FROM
foo1 arc
, foo1 newsub
WHERE
(newsub.description LIKE 'NEW%')
AND
(arc.description LIKE 'ARC%')
AND
(newsub.record_id = arc.record_id)

Finding The Sum OF Two Values In SQL Server 2008

I have a table Usage and it contains the following columns
sl_No
usage_ID
energyItem_ID
qty
unit_ID
location_ID
p_Rate
Sometimes the same EnergyItem might be located at different locations..
During those conditions how can I get the sum of qty of an individual energyItem..
How to get the sum of the qty of energyItems?
If I've understood correctly, you're trying to find the quantity of each
energy item, regardless of its location, using information in a single table.
The following query will give you the energyItem_ID of each item followed by the total quantity of each item:
SELECT energyItem_ID,Sum(qty) as TotalQuantity
FROM Usage
GROUP BY energyItem_ID
ORDER BY energyItem_ID
If, on the other hand, you wanted the quantity of each energy item, broken down by location, you would need the following:
SELECT location_ID,energyItemID,Sum(qty) as QuantityByLocation
FROM Usage
GROUP BY location_ID,energyItemID
ORDER BY location_ID,energyItemID
The order by clauses make the result easier to follow, but are not strictly necessary.
Finally, the answer by marc_s will give you the quantity of a specific energyItem.
How about:
SELECT EnergyItem_ID, SUM(qty)
FROM dbo.Usage
WHERE EnergyItem_ID = 42 -- or whatever ....
GROUP BY EnergyItem_ID
Or what are you looking for?? The question isn't very clear on the expected output....
select a.usage_ID , b.sum(p_Rate) as total from Table_1 a
inner join Table_2 as b on a.usage_ID = b.usage_ID
group by a.usage_ID

MySQL query not quite right...probably pretty simple

I've got a table for a payroll system, with four fields, and some sample data:
pkref employee_id new_wage effective_date
===== =========== ======== ==============
23 06031-BOB 10 080101
37 06031-BOB 15 090501
90 06031-BOB 13 110228
When an employee's wage is changed, a primary key reference auto-increments, and the appropriate information is recorded (effective_date is a timestamp, yymmdd). No problems there.
Now, I'm trying to get a query to find
All entries related to an employee, then
The maximum effective_date stamp in those sub-entries
The wage that corresponds to that maximum.
I've made my very first subquery ever (!), got it almost right, but it's buggy. Could some guru have a look and give me a bump in the right direction?
SELECT MAX(effective_date),new_wage FROM (SELECT effective_date,new_wage FROM hr_wages WHERE employee_code='06031-BOB') AS t1
Ideally, I want 110228 and 13 to be returned. But, as the aforementioned guru will no doubt see immediately, something is wrong. The new_wage value does not always match the max effective_date.
So. Vat to do?
Hang on, what's stopping you from doing the following?
select effective_date, new_wage from hr_wages
where employee_code = '06031-BOB'
order by effective_date desc
limit 1
For only one employee you can use IN with subquery
SELECT new_wage, other data...
FROM hr_wages
WHERE effective_date IN (SELECT max(effective_date) FROM hr_wages WHERE employee_code='06031-BOB')
AND employee_code='06031-BOB' -- Corrected: Credits to Stev
e
For all employees
SELECT new_wage, CO
FROM hr_wages w LEFT JOIN
(SELECT max(effective_date) effective_date, employee_code
FROM hr_wages
GROUP BY employee_code
)d ON w.employee_code = d.employee.code AND w.effective_date = d.effective_date
There was a post from #niktrs that provided the right answer, but it's been deleted!
So, here's the query I was looking for, with #niktrs help. If his post comes back, I'll accept it.
SELECT new_wage FROM hr_wages WHERE effective_date IN
(SELECT effective_date,new_wage FROM hr_wages WHERE employee_code='06031-BOB')
AND employee_code='06031-BOB'
This ugliness can be beautified, I'm sure.