Access: query crashes - sql

I have the following query (let's call it Query1) (kindly created here by Erik von Asmuth):
SELECT PARTNERID
,NAME
,FIRST_NAME
,UID
,DATA_R
FROM MY_TABLE
WHERE MY_TABLE.[DATA_R] = (
SELECT MAX(t.[DATA_R])
FROM MY_TABLE AS t
WHERE t.PARTNERID = MY_TABLE.PARTNERID
)
ORDER BY PARTNERID;
MY_TABLE has 20000 records and is a Query (even if the name might suggest the opposite) with the following form:
SELECT [MYTABLE_O].PARTNERID, [MYTABLE_O].NAME, [MYTABLE_O].FIRST_NAME, [MYTABLE_O].[Codice fiscale] AS CF, [MYTABLE_O].Date AS DATA_R
FROM [MYTABLE_O] LEFT JOIN [TO_EXCLUDE] ON [MYTABLE_O].[PARTNERID] = [TO_EXCLUDE].[PARTNERID]
WHERE ((([TO_EXCLUDE].PARTNERID) Is Null));
(I want to exclude some already considered elements that are in Table TO_EXCLUDE).
When I run the query (Query1) MS Access freezes. How can I avoid it/make it more efficient and stable?
I have tried to index in MYTABLE_O both PARTNERID AND DATA_R

You may have to write the result of the subquery:
SELECT PARTNERID, MAX([DATA_R]) AS MAXDATAR
FROM YourQuery
GROUP BY PARTNERID
to a temp table, and then replace in your query
FROM MY_TABLE AS t
with
FROM TempTable AS t

Related

Query to show all ID's except the ones that have a specific instrument

So I have a table which looks like this:
What would be the best query to exclude every "stuknr" that has atleast 1 "saxofoon" in the "instrumentnaam" column?
To select all stuknr where there is not stuknr with a saxofoon:
SELECT *
FROM table
WHERE stuknr not in (
SELECT stuknr
FROM TABLE
WHERE INSTRUMENTNAAM = ‘saxofoon’)
;
SELECT STUNKR
FROM TABLE
WHERE INSTRUMENTNAAM != ‘saxofoon’;
Here != (or <>, which are equivalent, see this) means "not equal".
You can do this with a NOT IN sub-select
select distinct
YT.stunkr
from
YourTable YT
where YT.stunkr NOT IN ( select distinct stunkr
from YourTable
where InstrumentNaam = 'saxofoon' )
So the sub-select is getting all IDs that DO have saxofoon and the primary select/from is getting where the ID is NOT in the secondary.

How can I improve the native query for a table with 7 millions rows?

I have the below view(table) in my database(SQL SERVER).
I want to retrieve 2 things from this table.
The object which has the latest booking date for each Product number.
It will return the objects = {0001, 2, 2019-06-06 10:39:58} and {0003, 2, 2019-06-07 12:39:58}.
If all the step number has no booking date for a Product number, it wil return the object with Step number = 1. It will return the object = {0002, 1, NULL}.
The view has 7.000.000 rows. I must do it by using native query.
The first query that retrieves the product with the latest booking date:
SELECT DISTINCT *
FROM TABLE t
WHERE t.BOOKING_DATE = (SELECT max(tbl.BOOKING_DATE) FROM TABLE tbl WHERE t.PRODUCT_NUMBER = tbl.PRODUCT_NUMBER)
The second query that retrieves the product with booking date NULL and Step number = 1;
SELECT DISTINCT *
FROM TABLE t
WHERE (SELECT max(tbl.BOOKING_DATE) FROM TABLE tbl WHERE t.PRODUCT_NUMBER = tbl.PRODUCT_NUMBER) IS NULL AND t.STEP_NUMBER = 1
I tried using a single query, but it takes too long.
For now I use 2 query for getting this information but for the future I need to improve this. Do you have an alternative? I also can not use stored procedure, function inside SQL SERVER. I must do it with native query from Java.
Try this,
Declare #p table(pumber int,step int,bookdate datetime)
insert into #p values
(1,1,'2019-01-01'),(1,2,'2019-01-02'),(1,3,'2019-01-03')
,(2,1,null),(2,2,null),(2,3,null)
,(3,1,null),(3,2,null),(3,3,'2019-01-03')
;With CTE as
(
select pumber,max(bookdate)bookdate
from #p p1
where bookdate is not null
group by pumber
)
select p.* from #p p
where exists(select 1 from CTE c
where p.pumber=c.pumber and p.bookdate=c.bookdate)
union all
select p1.* from #p p1
where p1.bookdate is null and step=1
and not exists(select 1 from CTE c
where p1.pumber=c.pumber)
If performance is main concern then 1 or 2 query do not matter,finally performance matter.
Create NonClustered index ix_Product on Product (ProductNumber,BookingDate,Stepnumber)
Go
If more than 90% of data are where BookingDate is not null or where BookingDate is null then you can create Filtered Index on it.
Create NonClustered index ix_Product on Product (ProductNumber,BookingDate,Stepnumber)
where BookingDate is not null
Go
Try row_number() with a proper ordering. Null values are treated as the lowest possible values by sql-server ORDER BY.
SELECT TOP(1) WITH TIES *
FROM myTable t
ORDER BY row_number() over(partition by PRODUCT_NUMBER order by BOOKING_DATE DESC, STEP_NUMBER);
Pay attention to sql-server adviced indexes to get good performance.
Possibly the most efficient method is a correlated subquery:
select t.*
from t
where t.step_number = (select top (1) t2.step_number
from t t2
where t2.product_number = t.product_number and
order by t2.booking_date desc, t2.step_number
);
In particular, this can take advantage of an index on (product_number, booking_date desc, step_number).

Query Optimization, Issue

Using SQL Server 2012;
I am using a query to find deltas in a table.
I have an archive table that has all the records with Licenceno PK,FileID
I want to find out how many Licenceno are in a fileId but are not in previous FileID.
Code Used:
Select count(*) from table where fileid = 123 and Licenceno not in (select Licenceno from table where fileid <123)
The code works fine but the problem is some of the fileIds have the same number of records as the previous ones but take 4 hours and are still running..
Is it a table issue?
Index cant be an issue as the whole table has
a non clustered index.
It is happening generally when i am calculating deltas for the latest Licenceno.
or Query planning is the issue?
I am not able to solve this for the past 5 days.
I would rewrite your query to use an exists clause, and also add an appropriate index:
SELECT COUNT(*)(
FROM yourTable t1
WHERE
fileid = 123 AND
NOT EXISTS (SELECT 1 FROM yourTable t2
WHERE t2.Licenseno = t1.Licenseno AND t2.fileid < 123);
An index on (Licenseno, fileid) might help here:
CREATE INDEX idx ON yourTable (Licenseno, fileid);
You may also try the came composite index in the reverse order:
CREATE INDEX idx ON yourTable (fileid, Licenseno);
Why not use count(distinct)?
select count(distinct licenseno)
from table
where fileid = 123;
For this query, you want an index on (fileid, licenseno).
You are complicating the logic by thinking sequentially ("have I seen this licenseno already?"). Instead, you just want to count the distinct values.
EDIT:
For this problem, you can try two levels of aggregation:
select count(*)
from (select licenseno, min(fileid) as min_fileid
from t
where licenseno <= 123
group by licenseno
) t
where min_fileid = 123;
How good the performance is relative to other approaches dependson how selective <= 123 is.
You could also use LAG for this
SELECT COUNT(*)
FROM (SELECT fileid,
LAG(fileid) OVER (PARTITION BY Licenceno ORDER BY fileid) AS prevFileID
FROM TABLE
WHERE fileid <= 123 ) D
WHERE fileid = 123
AND prevFileID IS NULL
... or an aggregation query ...
WITH T
AS (SELECT 1 AS Flag,
FROM TABLE
WHERE fileid <= 123
GROUP BY Licenceno
HAVING MIN(fileid) = 123 )
SELECT COUNT(*)
FROM T

Running query without intermediate data creation in sql

My query looks like this
CREATE TABLE work_pr.op1 AS
SELECT DISTINCT level1_idnt
,org_sales_price
FROM md1.item_lv1_org_price_m
WHERE fr_cntry_cde = '01';
CREATE TABLE work_pr.op2 AS
SELECT level1_idnt
,org_sales_price
FROM work_pr.op1
WHERE org_sales_price IS NOT NULL;
CREATE TABLE work_pr.final_op AS
SELECT level1_idnt
,avg(org_sales_price) AS op
FROM work_pr.op2
GROUP BY level1_idnt;
I want the steps to be in same sequence except that I dont want to create work_pr.op1 and the work_pr.op2 tables. How can I shorten this process in sql. I am very new to sql and any help will be greatly appreciated
You can just use nested selects in order to create a single table, the last one:
CREATE TABLE work_pr.final_op AS
SELECT level1_idnt
,avg(org_sales_price) AS op
FROM (
SELECT level1_idnt
,org_sales_price
FROM (
SELECT DISTINCT level1_idnt
,org_sales_price
FROM md1.item_lv1_org_price_m
WHERE fr_cntry_cde = '01'
) result_set_1
WHERE org_sales_price IS NOT NULL
) result_set_2
GROUP BY level1_idnt;
As #GordonLinoff mentioned, the SELECT can be simplified and you can use the one in his answer.
You can write the query as:
SELECT level1_idnt, AVG(org_sales_price) as op
FROM (SELECT DISTINCT level1_idnt, org_sales_price
FROM md1.item_lv1_org_price_m
WHERE fr_cntry_cde = '01' AND org_sales_price IS NOT NULL
) l
GROUP BY level1_idnt;
However, it should be unnecessary to have the DISTINCT in the subquery. Normally, the query would be simplified to:
SELECT level1_idnt, AVG(org_sales_price) as op
FROM md1.item_lv1_org_price_m
WHERE fr_cntry_cde = '01' AND org_sales_price IS NOT NULL
GROUP BY level1_idnt;

Removing SQL Duplicated Fields based on HistoryID

I have a database with duplicate values. Specifically SiteCode, LastName, FirstName, DateofService, Payer, BilledAmount, NetReceivable, and ContractualDiscount concatenate to form records that recur repeatedly throughout this table.
I'd like to remove all but one instance of these fields and am trying to do so by picking just one NetBilledHistoryID (which is a unique field for each record in the table).
Unfortunately, when I run this query, I still get the duplicated values.
How can I correct this so that my select query eliminates these duplicates? Or, even better, should I be using a different query technique all together?
SELECT *
FROM [Reports].[dbo].[NetBilledHistory] t1
WHERE EXISTS (
SELECT 1 FROM [Reports].[dbo].[NetBilledHistory] AS t2
WHERE t2.SiteCode = t1.SiteCode
AND t2.LastName = t1.LastName
AND t2.FirstName = t1.FirstName
AND t2.DateofService = t1.DateofService
AND t2.Payer = t1.Payer
AND t2.BilledAmount = t1.BilledAmount
AND t2.NetReceivable = t1.NetReceivable
AND t2.ContractualDiscount = t1.ContractualDiscount
AND t2.NetBilledHistoryID < t1.NetBilledHistoryID)
you can achieve that by using CTE:
WITH cte_query AS (
SELECT ROW_NUMBER() OVER(
partition by SiteCode, LastName, FirstName,
DateofService, Payer, BilledAmount, NetReceivable,
ContractualDiscount
order by NetBilledHistoryID) AS RowNum, *
FROM [Reports].[dbo].[NetBilledHistory]
)
SELECT * FROM cte_query where RowNum = 1;
adjust as needed to fit your purpose for columns, etc.