MOST RECENT VALUE (CAN ANYONE DO THIS) - sql

ive been told by my collegue to do this
"Perhaps what you can do is run a second table between #Basic and #Product where you only update the new retail column with the top 1 based on valid from desc for each currency code from #Basic?"
Create Table #Basic(
ProductCode Int,
ContractNo Int,
ProductDescription Varchar (max),
CGNo Nvarchar(MAX),
SCGNo Nvarchar(MAX),
EmpNo Int,
CurrencyCode NVARCHAR(MAX),
Retail decimal (38, 2),
ValidFrom datetime,
Active int,
ValidForCountry int
)
Insert Into #Basic
SELECT
c.ProductCode
,ContractNo
,p.Description
,p.CGNo
,p.SCGNo
,p.EmpNo
,r.CurrencyCode
,r.Retail
,r.ValidFrom
,p.active
,c.Validforcountry
FROM CONTRACT c
LEFT JOIN
(SELECT Distinct
ProductCode,
CurrencyCode,
Retail,
ValidFrom
From DIVRETAIL) as r on c.ProductCode = r.ProductCode
LEFT JOIN product p on c.ProductCode = p.ProductCode
WHERE ContractNo = 144546
And r.ValidFrom <= #enddate
SELECT Distinct
ProductCode,
CurrencyCode,
Retail,
ValidFrom
From DIVRETAIL
update #Basic
set Retail =(
select top 1 retail From DIVRETAIL
create table #basicretail
(ProductCode int
,ContractNo int
,Description varchar(MAX)
,CGNo int
,SCGNo int
,EmpNo int
,CurrencyCode varchar(10)
,Retail int
,ValidFrom datetime
,active int
,Validforcountry int
)
CREATE TABLE #Product
(
ProductCode Int,
ContractNo Int,
ProductDescription Varchar (max),
CGNo Nvarchar(MAX),
SCGNo Nvarchar(MAX),
EmpNo Int,
CurrencyCode NVARCHAR(MAX),
Retail decimal (38, 2),
ValidFrom datetime,
Active int,
ValidForCountry int,
Cost decimal (38,3)
)
INSERT INTO #Product
SELECT
ProductCode
,ContractNo
,ProductDescription
,CGNo
,SCGNo
,EmpNo
,CurrencyCode
,Retail
,ValidFrom
,Active
,ValidForCountry
,NULL
FROM #basic
UPDATE #Product
SET #Product.Cost =
(CASE WHEN #Product.CurrencyCode = 'EUR' THEN
(SELECT TOP 1
Case when c.IncoTermtype IN (1,9) then b.DDP/p.Packsize
when c.IncoTermtype IN (2,12) then b.DAT/p.Packsize
when c.IncoTermtype = 10 then (b.FOB+b.Freight)/p.Packsize
when c.IncoTermtype = 13 then (b.ExWorks+Freight)/p.Packsize else 0 End as Casecost
FROM braketvalue b
LEFT JOIN CONTRACT c on b.ContractNo = c.ContractNo
LEFT JOIN PRODUCT p on c.ProductCode = p.ProductCode
WHERE ValidFrom <= #enddate
AND b.DivNo like '8__'
AND #Product.CurrencyCode = 'EUR'
AND #Product.ContractNo = b.ContractNo)
ELSE
(SELECT TOP 1
Case when c.IncoTermtype IN (1,9) then b.DDP/p.Packsize
when c.IncoTermtype IN (2,12) then b.DAT/p.Packsize
when c.IncoTermtype = 10 then (b.FOB+b.Freight)/p.Packsize
when c.IncoTermtype = 13 then (b.ExWorks+Freight)/p.Packsize else 0 End as Casecost
FROM braketvalue b
LEFT JOIN CONTRACT c on b.ContractNo = c.ContractNo
LEFT JOIN PRODUCT p on c.ProductCode = p.ProductCode
WHERE ValidFrom <= #enddate
AND b.DivNo like '7__'
AND #Product.CurrencyCode = '£'
AND #Product.ContractNo = b.ContractNo)
END
)

I think you meant to say >= instead like
WHERE
r.ValidFrom >= '2015-01-07'
As well, move the conditions from WHERE clause to JOIN ON clause
From DIVTAIL) as r on c.ProductCode = r.ProductCode
AND r.ValidFrom >= '2015-01-07'
LEFT JOIN product p on c.ProductCode = p.ProductCode
AND p.CGNo = '01' AND p.SCGNo = '01' AND p.ProductCode = 3317

If you don't want an exact date you might have to do something like a date range that is calculated based on the date passed in. So your JOIN would be like LEFT JOIN ON date between BeginningDate and EndDate

Related

Display Customer and all of their order dates on single row

I have a customers table and an orders table. I want to display the customer and all of his/her order dates on one row, rather than multiple rows. Here is what I have and what I'm looking for:
Basic code to get results:
select customerid, name, orderdate
from customer_table c inner join
order_table o
on c.customerid = o.customerid
this will work at the most you cant show it on different columns having nulls:
select customer_id,name,LISTAGG(orderdate, ', ') WITHIN GROUP (ORDER BY orderdate)
from(select customerid, name, orderdate
from customer_table c inner join
order_table o
on c.customerid = o.customerid );
You can use the following because you're bound by the 12 order limit. If you expand to an unknown number of orders with no upper limit, then you would need to use dynamic SQL and even then it would be tricky, because you would also need to dynamically create unique column names.
This query batches by customer and sets the order values. They will be in dated order and set as NULL if there's no more orders. It kinda assumes that at least one customer has 12 orders. You'll get a column of all NULLS if that's not the case
IF OBJECT_ID('tempdb..#Results') IS NOT NULL DROP TABLE #Results
IF OBJECT_ID('tempdb..#sortedRows') IS NOT NULL DROP TABLE #SortedRows
DECLARE #CustomerList TABLE(CustomerID INT, RowNo INT);
INSERT INTO #CustomerList SELECT DISTINCT CustomerID, ROW_NUMBER() OVER(ORDER BY CustomerID) RowNo FROM Customer_Table (NOLOCK)
DECLARE #Count INT = (SELECT COUNT(DISTINCT CustomerID) RowNumber FROM #CustomerList)
DECLARE #Counter INT = 0
DECLARE #CustToProcess INT
CREATE TABLE #Results(CustomerID INT, [Name] VARCHAR(50), OrderDate1 DATETIME,
OrderDate2 DATETIME, OrderDate3 DATETIME, OrderDate4 DATETIME, OrderDate5 DATETIME,
OrderDate6 DATETIME, OrderDate7 DATETIME, OrderDate8 DATETIME, OrderDate9 DATETIME,
OrderDate10 DATETIME, OrderDate11 DATETIME, OrderDate12 DATETIME)
INSERT INTO #Results(CustomerID, Name) SELECT DISTINCT CustomerID, Name FROM Customer_Table
SELECT ROW_NUMBER() OVER(PARTITION BY c.CustomerID ORDER BY OrderDate) RowNo,
c.CustomerID, c.Name, t.OrderDate INTO #SortedRows
FROM Customer_Table c (NOLOCK) JOIN Order_Table t ON c.CustomerID = t.CustomerID
WHILE #Counter < #Count
BEGIN
SET #Counter += 1
SET #CustToProcess = (SELECT CustomerID FROM #CustomerList WHERE RowNo = #Counter)
PRINT #CustToProcess
SELECT * INTO #RowsForProcessing FROM #SortedRows WHERE CustomerID = #CustToProcess
UPDATE #Results SET OrderDate1 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 1) WHERE CustomerID = #CustToProcess
UPDATE #Results SET OrderDate2 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 2) WHERE CustomerID = #CustToProcess
UPDATE #Results SET OrderDate3 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 3) WHERE CustomerID = #CustToProcess
UPDATE #Results SET OrderDate4 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 4) WHERE CustomerID = #CustToProcess
UPDATE #Results SET OrderDate5 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 5) WHERE CustomerID = #CustToProcess
UPDATE #Results SET OrderDate6 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 6) WHERE CustomerID = #CustToProcess
UPDATE #Results SET OrderDate7 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 7) WHERE CustomerID = #CustToProcess
UPDATE #Results SET OrderDate8 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 8) WHERE CustomerID = #CustToProcess
UPDATE #Results SET OrderDate9 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 9) WHERE CustomerID = #CustToProcess
UPDATE #Results SET OrderDate10 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 10) WHERE CustomerID = #CustToProcess
UPDATE #Results SET OrderDate11 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 11) WHERE CustomerID = #CustToProcess
UPDATE #Results SET OrderDate12 = (SELECT OrderDate FROM #RowsForProcessing WHERE Rowno = 12) WHERE CustomerID = #CustToProcess
DROP Table #RowsForProcessing
END
SELECT * FROM #Results
Try this if you use MS SQL Server:
-- 1st, get the number of columns
declare #columnnumber int = 1
select #columnnumber = max(a.count)
from (
select c.cid,c.name, count(o.orderdate) as count
from
customer_table c
join order_table o
on c.cid = o.cid
group by c.cid,c.name)a
print #columnnumber
-- Compose the column names for Pivot
declare #columnname varchar(max) = ''
declare #int int = 1
while #int <= #columnnumber
begin
set #columnname = #columnname + '[date' + cast(#int as varchar(10))+ '],'
set #int = #int + 1
end
set #columnname = '('+left(#columnname,len(#columnname)-1)+')'
print #columnname
--Pivot !!! + Dynamic SQL
declare #str varchar(max)
set #str =
'SELECT *
FROM
(SELECT c.cid,c.name, o.orderdate,concat(''date'',row_number() over (partition by c.cid,c.name order by o.orderdate)) rnk
FROM customer_table c
join order_table o
on c.cid = o.cid) AS s
PIVOT
(
min(s.orderdate)
FOR s.rnk IN '+ #columnname+
' ) AS PivotTable'
print #str
execute (#str)
Please change the column name. I used cid as your customerid.
Output:
cid name date1 date2 date3
12 John 2017-03-04 2017-05-26 2017-12-01
4 Nancy 2017-02-01 NULL NULL
Like others said, it's in principle impossible (in pure SQL) to generate this not knowing how many orders you have for a single customer.
I like #nikhil-sugandh's answer, it works great if you are OK with having all orders comma-separated in a single column.
If you insist on having multiple columns, you can build on that answer, by replacing LISTAGG with ARRAY_AGG and postprocessing it. It will be MUCH more efficient than e.g. the proposed solution with multiple joins. You can also use ARRAY_SLICE to handle cases when there are more orders than you are prepared for.
Example (note, I added an extra order to demonstrate handling more-than-expected orders
create or replace table customer_table(customerId int, name varchar)
as select * from values
(12,'John'),(4,'Nancy');
create or replace table order_table(orderId int, customerId int, orderDate date)
as select * from values
(1,12,'3/4/2017'),(2,12,'5/26/2017'),(3,12,'12/1/2017'),(4,4,'2/1/2017'),(5,12,'1/1/2019');
with subq as (
select c.customerid, name,
array_agg(orderdate) within group (order by orderdate) as orders
from customer_table c
inner join order_table o on c.customerid = o.customerid
group by c.customerid, c.name
)
select customerid, name,
orders[0]::date AS order1, orders[1]::date AS order2,
array_to_string(array_slice(orders, 2, 999), ' , ') AS overflow
from subq;
------------+-------+------------+------------+-------------------------+
CUSTOMERID | NAME | ORDER1 | ORDER2 | OVERFLOW |
------------+-------+------------+------------+-------------------------+
4 | Nancy | 2017-02-01 | [NULL] | |
12 | John | 2017-03-04 | 2017-05-26 | 2017-12-01 , 2019-01-01 |
------------+-------+------------+------------+-------------------------+
first create a view like this:
create view order_view as
select
count(*) over (partition by customerId order by orderDate) as ord,
CustomerId,
orderdate
from order_table
then you can use this query:
select c.customerid,
o1.orderdate,
o2.orderdate
o3.orderdate
.
.
.
o12.orderdate
from customer_table c
left join order_view o1
on c.customerid = o1.customerid and ord = 1
left join order_view o2
on c.customerid = o2.customerid and ord = 2
left join order_view o3
on c.customerid = o3.customerid and ord = 3
.
.
.
left join order_view o12
on c.customerid = o12.customerid and ord = 12

Select columns without group by in aggregate

I'm using SQL Server 2014. I have a structure like this:
Id BIGINT,
ItemName NVARCHAR(4000),
RecordDate DATETIME2,
Supplier NVARCHAR(450),
Quantity DECIMAL(18, 2),
ItemUnit NVARCHAR(2000),
EntityUnit NVARCHAR(2000),
ItemSize DECIMAL(18, 2),
PackageSize DECIMAL(18, 2),
FamilyCode NVARCHAR(20),
Family NVARCHAR(500),
CategoryCode NVARCHAR(20),
Category NVARCHAR(500),
SubCategoryCode NVARCHAR(20),
SubCategory NVARCHAR(500),
ItemGroupCode NVARCHAR(20),
ItemGroup NVARCHAR(500),
PurchaseValue DECIMAL(18, 2),
UnitPurchaseValue DECIMAL(18, 2),
PackagePurchaseValue DECIMAL(18, 2),
FacilityCode NVARCHAR(450),
CurrencyCode NVARCHAR(5)
I'd like to select distinct ItemNames from BatchRecords table paired with the max Id among the items with the same ItemName as well as Supplier, Quantity and other values of the item with the max Id for each ItemName. So far, I came up with the following SP, definitely it doesn't work yet as GROUP BY throws an error.
I could probably use a subquery, but then how do I satisfy the condition with max Ids for each unique ItemName? Also, any input to the stored procedure quality/obvious bottleneck is highly appreciated as it has to be somewhat quick.
CREATE PROCEDURE dbo.GetRecordsPageFlat
(#BatchIds dbo.GenericIntArray READONLY,
#FileRequestId INT,
#PageSize INT,
#PageCount INT,
#LastId BIGINT,
#NameMaskValue NVARCHAR(128) = NULL,
#NameMaskType INT = NULL,
#FamilyCodeMaskValue NVARCHAR(128),
#CategoryCodeMaskValue NVARCHAR(128),
#SubCategoryCodeMaskValue NVARCHAR(128)
)
AS
SET NOCOUNT ON;
DECLARE #Temp dbo.RecordImportStructure
DECLARE #ErrorCode INT
DECLARE #Step NVARCHAR(200)
DECLARE #Rows INT
--OUTPUT ##ROWCOUNT
--OUTPUT INSERTED.Id
INSERT INTO #Temp (
Id,
ItemName,
Supplier,
Quantity,
ItemUnit,
EntityUnit,
ItemSize,
PackageSize,
PurchaseValue,
UnitPurchaseValue,
PackagePurchaseValue,
CurrencyCode
)
SELECT
BR.Id,
BR.ItemName,
BR.Supplier,
BR.Quantity,
BR.ItemUnit,
BR.EntityUnit,
BR.ItemSize,
BR.PackageSize,
BR.ItemGroup,
BR.UnitPurchaseValue,
BR.PackagePurchaseValue,
C.IsoCode
FROM
dbo.BatchRecords BR
LEFT OUTER JOIN
dbo.FacilityInstances F ON F.Id = BR.FacilityInstanceId
LEFT OUTER JOIN
dbo.Currencies C ON C.Id = BR.CurrencyId
--OPTION(RECOMPILE)
WHERE
BR.DataBatchId IN (SELECT * FROM #BatchIds)
AND BR.Id > #LastId
AND (#FamilyCodeMaskValue IS NULL OR BR.FamilyCode = #FamilyCodeMaskValue)
AND (#CategoryCodeMaskValue IS NULL OR BR.CategoryCode = #CategoryCodeMaskValue)
AND (#SubCategoryCodeMaskValue IS NULL OR BR.SubCategoryCode = #SubCategoryCodeMaskValue)
AND (#NameMaskType IS NULL AND #NameMaskValue IS NULL
OR ((#NameMaskType = 1 AND BR.ItemName LIKE #NameMaskValue + '%')
OR (#NameMaskType = 2 AND BR.ItemName LIKE '%' + #NameMaskValue)
OR (#NameMaskType = 3 AND BR.ItemName LIKE '%' + #NameMaskValue + '%')
))
GROUP BY
BR.ItemName
ORDER BY
BR.Id
OFFSET #PageCount * #PageSize ROWS
FETCH NEXT #PageSize ROWS ONLY;
UPDATE dbo.BatchActionRequests
SET PageNumber = #PageCount+1,
LatestItemId = (SELECT MAX(Id) FROM #Temp)
WHERE Id = #FileRequestId
It looks like a top-n-per-group problem.
There are two common approaches to it: using ROW_NUMBER and CROSS APPLY. Here is the ROW_NUMBER variant. See Get top 1 row of each group for details.
WITH
CTE
AS
(
SELECT
BR.Id,
BR.ItemName,
BR.Supplier,
BR.Quantity,
BR.ItemUnit,
BR.EntityUnit,
BR.ItemSize,
BR.PackageSize,
-- BR.ItemGroup,???
BR.UnitPurchaseValue,
BR.PackagePurchaseValue,
C.IsoCode AS CurrencyCode,
ROW_NUMBER() OVER (PARTITION BY BR.ItemName ORDER BY BR.Id DESC) AS rn
FROM
dbo.BatchRecords BR
LEFT OUTER JOIN dbo.FacilityInstances F ON F.Id = BR.FacilityInstanceId
LEFT OUTER JOIN dbo.Currencies C ON C.Id = BR.CurrencyId
WHERE
BR.DataBatchId IN (SELECT * FROM #BatchIds)
AND BR.Id > #LastId
AND (#FamilyCodeMaskValue IS NULL OR BR.FamilyCode = #FamilyCodeMaskValue)
AND (#CategoryCodeMaskValue IS NULL OR BR.CategoryCode = #CategoryCodeMaskValue)
AND (#SubCategoryCodeMaskValue IS NULL OR BR.SubCategoryCode = #SubCategoryCodeMaskValue)
AND (#NameMaskType IS NULL AND #NameMaskValue IS NULL
OR ((#NameMaskType = 1 AND BR.ItemName LIKE #NameMaskValue + '%')
OR (#NameMaskType = 2 AND BR.ItemName LIKE '%' + #NameMaskValue)
OR (#NameMaskType = 3 AND BR.ItemName LIKE '%' + #NameMaskValue + '%')
))
)
INSERT INTO #Temp (
Id,
ItemName,
Supplier,
Quantity,
ItemUnit,
EntityUnit,
ItemSize,
PackageSize,
-- PurchaseValue,???
UnitPurchaseValue,
PackagePurchaseValue,
CurrencyCode
)
SELECT
Id,
ItemName,
Supplier,
Quantity,
ItemUnit,
EntityUnit,
ItemSize,
PackageSize,
-- PurchaseValue,???
UnitPurchaseValue,
PackagePurchaseValue,
CurrencyCode
FROM CTE
WHERE rn = 1
ORDER BY
Id
OFFSET #PageCount * #PageSize ROWS
FETCH NEXT #PageSize ROWS ONLY
OPTION(RECOMPILE);
For each ItemName the query will pick the row with the largest Id.
;WITH CTC
AS
(
SELECT MAX(BR.ID) AS Id, BR.ItemName
FROM dbo.BatchRecords BR
LEFT OUTER JOIN dbo.FacilityInstances F ON F.Id = BR.FacilityInstanceId
WHERE BR.DataBatchId IN (SELECT * FROM #BatchIds)
AND BR.Id > #LastId
AND (#FamilyCodeMaskValue IS NULL OR BR.FamilyCode = #FamilyCodeMaskValue)
AND (#CategoryCodeMaskValue IS NULL OR BR.CategoryCode = #CategoryCodeMaskValue)
AND (#SubCategoryCodeMaskValue IS NULL OR BR.SubCategoryCode = #SubCategoryCodeMaskValue)
AND (#NameMaskType IS NULL AND #NameMaskValue IS NULL
OR ((#NameMaskType = 1 AND BR.ItemName LIKE #NameMaskValue + '%')
OR (#NameMaskType = 2 AND BR.ItemName LIKE '%' + #NameMaskValue)
OR (#NameMaskType = 3 AND BR.ItemName LIKE '%' + #NameMaskValue + '%')
))
GROUP BY
BR.ItemName
)
INSERT INTO #Temp (
Id,
ItemName,
Supplier,
Quantity,
ItemUnit,
EntityUnit,
ItemSize,
PackageSize,
PurchaseValue,
UnitPurchaseValue,
PackagePurchaseValue,
CurrencyCode
)
SELECT BR.Id,
BR.ItemName,
BR.Supplier,
BR.Quantity,
BR.ItemUnit,
BR.EntityUnit,
BR.ItemSize,
BR.PackageSize,
BR.ItemGroup,
BR.UnitPurchaseValue,
BR.PackagePurchaseValue,
C.IsoCode
FROM CTC t
JOIN dbo.BatchRecords BR ON t.Id = BR.Id
LEFT OUTER JOIN dbo.Currencies C ON C.Id = BR.CurrencyId
ORDER BY BR.Id
OFFSET #PageCount * #PageSize ROWS
FETCH NEXT #PageSize ROWS ONLY;

suddenly query executing slowly

I have very typical situation where I'm doing wrong. I have query which have executed fast initially but later on it taking loads of time to execute ..
My query :
Declare
#fromdate varchar(20) = '01/01/2014',
#todate varchar(20)= '27/05/2015',
#SERVICE_ID CHAR(5) = '123'
DECLARE #FDATE DATETIME ,
#TDATE DATETIME
SET #FDATE = (CONVERT(DATETIME,#fromdate,103))
SET #TDATE = (CONVERT(DATETIME,#todate,103))
IF OBJECT_ID('tempdb..#RUID') IS NOT NULL
DROP TABLE #RUID
CREATE TABLE #RUID(
OFFICEID INT,
OFFICE_TITTLE INT,
MAIN_OFFICE_TITTLE VARCHAR(50),
RLB_NAME VARCHAR(20),
DIST_NAME INT,
district_description VARCHAR(30))
CREATE CLUSTERED INDEX IDX_C_RUID_ID ON #RUID(OFFICEID)
CREATE NONCLUSTERED INDEX IDX_RUID_Name ON #RUID(OFFICE_TITTLE,DIST_NAME)INCLUDE(district_description)
INSERT INTO #RUID
SELECT OFFICEID,
OFFICE_TITTLE,
MAIN_OFFICE_TITTLE,
RLB_NAME,
DIST_NAME,
D.district_description
FROM APSDC..DISTRICT D
INNER JOIN cdma..Unified_RUID_WARD_MSTR I WITH(NOLOCK)
ON D.CDMA_DistrictID = I.DIST_NAME
WHERE RLB_NAME in(3) AND I.STATEID ='01'
select C.MAIN_OFFICE_TITTLE AS 'OFFICE_TITTLE',C.officeid, C.DIST_NAME AS DistrictName, C.district_description,
ISNULL(count(I.ApplicationNumber),0) 'Total_Trans',
isnull(sum(case when Data_Available='Y' AND DataTampered = 'N' then 1 else 0 end),0) 'CategoryA'
from #RUID c with(nolock)
LEFT JOIN Unified_BirthDeathAppDetails I WITH(NOLOCK) ON
(C.OFFICE_TITTLE=I.RUID AND C.DIST_NAME=I.DistrictName)
AND I.Service_Type= '01' AND
(DATEADD(DD,0,DATEDIFF(DD,0,I.Created_Date))) BETWEEN #FDATE AND #TDATE
AND NOT EXISTS(select application_number from reversal_details WITH(NOLOCK) WHERE ApplicationNumber <> i.ApplicationNumber AND service_id='123' )
group by C.MAIN_OFFICE_TITTLE,C.officeid, C.DIST_NAME,C.district_description
order by C.district_description ,C.MAIN_OFFICE_TITTLE
I have tried with #temp table and table variable but it is not even showing any result set. But the same query executed in 2 secs now it is taking lot of time. I have tried UPDATE Statstics on this tables and I have checked with locking also. What I need to do I have followed every other peformance optimized techinique.
Try:
Declare
#FDate Date = '01/01/2014',
#TDate Date= '27/05/2015',
#SERVICE_ID CHAR(5) = '123'
;WITH RUID
AS
(
SELECT OFFICEID,
OFFICE_TITTLE,
MAIN_OFFICE_TITTLE,
RLB_NAME,
DIST_NAME,
D.district_description
FROM APSDC..DISTRICT D
INNER JOIN cdma..Unified_RUID_WARD_MSTR I
ON D.CDMA_DistrictID = I.DIST_NAME
WHERE RLB_NAME in(3) AND I.STATEID ='01'
),
AppDetails
AS
(
SELECT ApplicationNumber,
CASE WHEN Data_Available='Y' AND DataTampered = 'N'
THEN 1
ELSE 0
END CategoryA
FROM Unified_BirthDeathAppDetails I
WHERE I.CreateDate >= #FDate AND I.CreatedDate < #TDate AND
NOT EXISTS
( select application_number
FROM reversal_details
WHERE I.Service_Type= '01' AND
ApplicationNumber <> i.ApplicationNumber AND
service_id= #Service_iD
)
)
SELECT C.MAIN_OFFICE_TITTLE AS OFFICE_TITTLE
,C.officeid, C.DIST_NAME AS DistrictName
, C.district_description
,ISNULL(count(I.ApplicationNumber),0) Total_Trans
,isnull(sum(CategoryA),0) CategoryA
FROM RUID c
LEFT JOIN AppDetails I
ON C.OFFICE_TITTLE=I.RUID AND C.DIST_NAME=I.DistrictName
GROUP BY C.MAIN_OFFICE_TITTLE
,C.officeid
,C.DIST_NAME
,C.district_description
ORDER BU C.district_description
,C.MAIN_OFFICE_TITTLE
Make sure you have decent indexes on RLB_name, StateId, CDMA_DistrictId, Dist_Name, CreatedDate etc.

Rewriting SQL query to simplify logic

I'm quite a newbie in optimizing queries.. it would be a first for me to handle other persons query and optimize it to improve performance. Can you kindly give me advice on which part of the query could I simplify in order to improve its performance....
CREATE FUNCTION SALES
(#SUPPLIERCODE VARCHAR(15),
#BATCHID VARCHAR(50))
RETURNS
#STOCKDETAILS TABLE([ID] CHAR(1),
[BATCH RECEIVEDATE] DATETIME,
SUPPLIERCODE VARCHAR(15),
[NOW - RECEVEDATE] INT,
[DUEDATE] VARCHAR(50)
)
AS
BEGIN
DECLARE #RECEIVEDATE DATETIME,
#SUPPLIERCODE1 VARCHAR(15)
SELECT TOP 1
#RECEIVEDATE = O.ReceivedDate,
#SUPPLIERCODE1 = A.SUPPLIERCODE
FROM
TRANSACT.dbo.FIELDS A WITH(NOLOCK)
INNER JOIN
TRANSACT.dbo.DELIV O WITH(NOLOCK) ON O.BATCHID = A.BATCHID
DECLARE #ID1 TABLE(SUPPLIERCODE VARCHAR(50))
INSERT INTO #ID1
SELECT P.SUPPLIERCODE
FROM
(SELECT
[SUPPLIERCODE] = SUPPLIERCODE,
[TOTAL] = ISNULL(SUM(ITEMPRICE + (ITEMPRICE * .12)), 0)
FROM TRANSACT.dbo.ProviderDiscount WITH(NOLOCK)
WHERE ACQUIREDDATE <> '1900-01-01 00:00:00.000'
AND SUPPLIERCODE = #SUPPLIERCODE1
GROUP BY SUPPLIERCODE) P
WHERE P.TOTAL <> 0
DECLARE #ID TABLE ([BATCH RECEIVEDATE] DATETIME,
SUPPLIERCODE VARCHAR(15),
ACQUIREDDATE DATETIME,
Coverage VARCHAR(20),
CoverageItem VARCHAR(10),
[NOW - RECEVEDATE] INT,
DiscTerm1 INT, DiscTerm2 INT,
DiscTerm3 INT, DiscTerm4 INT,
DiscTerm5 INT,
[NEW ACQUIREDDATE] VARCHAR(50)
)
INSERT INTO #ID
SELECT DISTINCT
[BATCH RECEIVEDATE] = #RECEIVEDATE,
B.SUPPLIERCODE,
B.ACQUIREDDATE,
B.Coverage,
B.CoverageItem,
[NOW - RECEVEDATE] = DATEDIFF(DAY,#RECEIVEDATE,GETDATE()),
B.DiscTerm1, B.DiscTerm2, B.DiscTerm3,
B.DiscTerm4, B.DiscTerm5,
[NEW ACQUIREDDATE] = TRANSACT.dbo.fxnGetIDNewACQUIREDDATE(B.DiscTerm1, B.DiscTerm2, B.DiscTerm3, B.DiscTerm4, B.DiscTerm5, #RECEIVEDATE)
FROM
TRANSACT.dbo.ProviderDiscount B WITH(NOLOCK)
INNER JOIN
(SELECT
[ACQUIREDDATE] = MAX(ACQUIREDDATE),
[REOD] = MAX(REOD)
FROM
TRANSACT.dbo.ProviderDiscount B2 WITH(NOLOCK)
INNER JOIN
#ID1 B1 ON B1.SUPPLIERCODE = B2.SUPPLIERCODE
WHERE
B2.Coverage = #CLAIMTYPE
AND B2.ACQUIREDDATE < #RECEIVEDATE) B3 ON B3.REOD = B.REOD
INSERT INTO #STOCKDETAILS
SELECT DISTINCT
[ID] = 'Y',
[BATCH RECEIVEDATE],
SUPPLIERCODE,
[NOW - RECEVEDATE],
[DUEDATE] = MIN([NEW ACQUIREDDATE])
FROM
#ID
WHERE
ISNULL([NEW ACQUIREDDATE],'NONE') <> 'NONE'
GROUP BY
[BATCH RECEIVEDATE], SUPPLIERCODE, [NOW - RECEVEDATE]
RETURN
END
Well, here's one thing you can do.
DECLARE #ID1 TABLE(SUPPLIERCODE VARCHAR(50))
INSERT INTO #ID1
SELECT P.SUPPLIERCODE
FROM
(
SELECT
[SUPPLIERCODE] = SUPPLIERCODE,
[TOTAL] = ISNULL(SUM(ITEMPRICE+(ITEMPRICE*.12)),0)
FROM TRANSACT.dbo.ProviderDiscount WITH(NOLOCK)
WHERE ACQUIREDDATE <> '1900-01-01 00:00:00.000'
AND SUPPLIERCODE = #SUPPLIERCODE1
GROUP BY SUPPLIERCODE
) P
WHERE P.TOTAL <> 0
Can be rewritten stripped of lots of extra. Maybe even more than I do here:
DECLARE #ID1 TABLE(SUPPLIERCODE VARCHAR(50))
INSERT INTO #ID1
SELECT SUPPLIERCODE
FROM TRANSACT.dbo.ProviderDiscount WITH(NOLOCK)
WHERE ACQUIREDDATE <> '1900-01-01 00:00:00.000'
AND SUPPLIERCODE = #SUPPLIERCODE1
GROUP BY SUPPLIERCODE
HAVING ISNULL(SUM(ITEMPRICE),0) <> 0
This almost looks like test question for refactoring SQL.

Comparing Sum from 2 different Columns

I'm trying to compare the sum of 2 different columns and I'm getting an error saying that I must declare #Base. Then I have tried to do something like #Base AS B, the error will disappear. But I'm not retrieving any data.
Can anyone help me with if I have made a typo or my INNER JOIN is wrong?
Declare #Base table(PickupDate smalldatetime, DeliveryDate smalldatetime, PickupAdrID int, PickupCustID varchar(10), DeliveryType char, DeliveryAdrID int, DeliveryCustID varchar(10), DeliveryAlias varchar (30), Volumen float, Weight float) Insert #Base(PickupDate,DeliveryDate, PickupAdrID, PickupCustID, DeliveryType, DeliveryAdrID, DeliveryCustID, DeliveryAlias, Volumen,Weight)
SELECT PickupDate,DeliveryDate, PickupAdrID, PickupCustID, DeliveryType, DeliveryAdrID, DeliveryCustID, DeliveryAlias, Volumen, Weight
FROM Sending
INNER JOIN Address_ViewI ON Sending.PickupAdrID = Address_ViewI.AdrID
INNER JOIN Address_ViewI AS Address_View_DE ON Sending.DeliveryAdrID = Address_View_DE.AdrID
WHERE (Address_ViewI.CountryUK = #puC AND Address_View_DE.CountryUK = #deC) AND (Sending.PickupDate >= #start) AND (Sending.PickupDate < #end) AND ((PickUpCustID Like 'TMHSE' OR DeliveryCustID like 'TMHSE' ) )
OR (Address_ViewI.CountryUK = #puC AND Address_View_DE.CountryUK = #deC) AND (Sending.PickupDate >= #start) AND (Sending.PickupDate < #end) AND ((PickUpCustID Like 'SomeName' OR DeliveryCustID like 'SomeName' ) )
SELECT totals.DeliveryAdrID, totals.PickupDate,
(CASE WHEN weightTOTAL <= volumenTOTAL THEN volumenTOTAL
WHEN weightTOTAL >= volumenTOTAL THEN weightTOTAL ELSE weightTOTAL END) AS InvoiceWeight
FROM #Base INNER JOIN
(SELECT DeliveryAdrID, CONVERT(CHAR(10),PickupDate,110) AS PickupDate,
CEILING(SUM(CASE Weight When 0 Then #zeroKiloVal ELSE Weight END)) AS WeightTOTAL,
CEILING(SUM(CASE Volumen WHEN 0 THEN (#zeroVoluVal * #zeroVoluFac) ELSE Volumen END)) AS volumenTOTAL,
COUNT(DeliveryAdrID)AS Packages
FROM #Base GROUP BY CONVERT(CHAR(10),PickupDate,110), DeliveryAdrID ) AS totals
ON #Base.DeliveryAdrID = totals.DeliveryAdrID AND CONVERT(CHAR(10),#Base.PickupDate,110) = totals.PickupDate
The full code is listed here http://pastie.org/8238866
And the error I'm getting
It worked for me when I placed an alias on the reference to #Base
Declare #zeroKiloVal float = 10
Declare #zeroVoluVal float = 10
Declare #zeroVoluFac float = 200
Declare #puC varchar = 'Sweden'
Declare #deC varchar = 'Sweden'
Declare #start smalldatetime = '2013-04-21'
Declare #end smalldatetime = '2013-05-01'
DECLARE #Base TABLE (SendingID INT, Barcode VARCHAR(50), PickupType CHAR, PickupDate SMALLDATETIME, DeliveryDate SMALLDATETIME, PickupAdrID INT, PickupCustID VARCHAR(10), DeliveryType CHAR, DeliveryAdrID INT, DeliveryCustID VARCHAR(10), DeliveryAlias VARCHAR (30), Volumen FLOAT, [Weight] FLOAT)
INSERT INTO #Base(SendingID, Barcode, PickupType, PickupDate,DeliveryDate, PickupAdrID, PickupCustID, DeliveryType, DeliveryAdrID, DeliveryCustID, DeliveryAlias, Volumen,[Weight])
SELECT SendingID = 1, Barcode= 1, PickupType= 1, PickupDate= 1,DeliveryDate= 1, PickupAdrID= 1, PickupCustID= 1, DeliveryType= 1, DeliveryAdrID= 1, DeliveryCustID= 1, DeliveryAlias= 1, Volumen= 1, [Weight] = 1
-- Replacing below code with stubbed data for testing.
-- SELECT SendingID, Barcode, PickupType, PickupDate,DeliveryDate, PickupAdrID, PickupCustID, DeliveryType, DeliveryAdrID, DeliveryCustID, DeliveryAlias, Volumen, Weight
-- FROM Sending
-- INNER JOIN Address_ViewI ON Sending.PickupAdrID = Address_ViewI.AdrID
-- INNER JOIN Address_ViewI AS Address_View_DE ON Sending.DeliveryAdrID = Address_View_DE.AdrID
-- WHERE (Address_ViewI.CountryUK = #puC AND Address_View_DE.CountryUK = #deC) AND (Sending.PickupDate >= #start) AND (Sending.PickupDate < #end) AND ((PickUpCustID Like 'TMHSE' OR DeliveryCustID like 'TMHSE' ) )
-- OR (Address_ViewI.CountryUK = #puC AND Address_View_DE.CountryUK = #deC) AND (Sending.PickupDate >= #start) AND (Sending.PickupDate < #end) AND ((PickUpCustID Like 'TMHSE' OR DeliveryCustID like 'TMHSE' ) )
SELECT totals.DeliveryAdrID
, totals.PickupDate
, InvoiceWeight =
(
CASE WHEN weightTOTAL <= volumenTOTAL THEN volumenTOTAL
WHEN weightTOTAL >= volumenTOTAL THEN weightTOTAL ELSE weightTOTAL END
)
FROM #Base AS B -- <<Added alias here>>
INNER JOIN
(
SELECT DeliveryAdrID
, PickupDate = CONVERT(CHAR(10),PickupDate,110)
, WeightTOTAL = CEILING(SUM(CASE [Weight] WHEN 0 THEN #zeroKiloVal ELSE [Weight] END))
, volumenTOTAL = CEILING(SUM(CASE Volumen WHEN 0 THEN (#zeroVoluVal * #zeroVoluFac) ELSE Volumen END))
, Packages = COUNT(DeliveryAdrID)
FROM #Base
GROUP BY CONVERT(CHAR(10),PickupDate,110), DeliveryAdrID
) AS totals ON B.DeliveryAdrID = totals.DeliveryAdrID
AND CONVERT(CHAR(10),B.PickupDate,110) = totals.PickupDate
Maybe you need to use some wildcards in the constants being compared with the Like operator, such as:
PickUpCustID Like '%TMHSE%' OR DeliveryCustID like '%TMHSE%'
Otherwise, I think you're just doing the same as
PickUpCustID = 'TMHSE' OR DeliveryCustID = 'TMHSE'
or
'TMHSE' in (PickUpCustID, DeliveryCustID)
I figured out the error it seems that my declared variables was missing something:
Declare #puC varchar = 'Sweden'
Declare #deC varchar = 'Sweden'
I changed it to
Declare #puC varchar (50) = 'Sweden'
Declare #deC varchar (50) = 'Sweden'
Thanks for your time guys