DATEDIFF displaying null values - sql

I have used DATEDIFF to distinguish between when the first unit rate was created and the posting date is when the first transaction of that item was posted.
I have the result that I need , however the DateDiff function gives me NULL values starting date for some rows.
SELECT DISTINCT b.[Entry No_] ,
a.[Starting Date],
b.[Posting Date],
b.[Item No_],
b.[Invoiced Quantity],
a.[Litre Conversion Factor],
a.[Unit Rate] ,
b.[Location Code],
a.[Excise Location],
a.[Excise Type Code],
a.[Unit Of Measure Code]
FROM [Spier Live$Value Entry] b
LEFT JOIN [Transfer Excise Tbl] a
ON a.[No_] = b.[Item No_]
AND b.[Location Code] = a.[Location Code]
AND DateDiff(y,b.[Posting Date],a.[Starting Date]) > -365 --DateDiff Year -365 for starting date
AND DateDiff(y,b.[Posting Date],a.[Starting Date]) < 0 --DateDiff Yer < 0 for posting date
WHERE b.[Posting Date] > '2013-02-26' --This is when the unit rate was entered
AND b.[Gen_ Bus_ Posting Group] IN ('LOCA','EXSA')
AND b.[Invoiced Quantity] <>0 --Removing all zero values
AND b.[Item No_] = 'F00335'
ORDER BY b.[Posting Date]
My Result
Transfer Excise Tbl This is the table I am joining on

As alex points out in the comments, you're looking for things with datediffs based on day of year, not year. Did you mean <= 0, btw? These criteria don't make sense and so probably aren't what you really want. If so, they'd cause joins to fail where you don't really want them to, leading to nulls showing for table a columns.

Related

SQL create column for every week (Loop?)

I need to make a report for weekly changes.
This is the code for todays amount
SELECT
[Entry No_],
[Customer No_],
[Posting Date],
[Description],
[Currency Code],
Trans_type = case when [Deposit]=1 then 'Deposit'
when [Imprest]=1 then 'Imprest'
else 'Other' end,
A.Amount
FROM Table1
LEFT JOIN
(
SELECT Distinct [Cust_ Ledger Entry No_],
SUM ([Amount EUR]) as 'amount'
FROM Table2
group by [Cust_ Ledger Entry No_]
having
SUM ([Amount EUR]) <> '0'
)A
on [Entry No_] = A.[Cust_ Ledger Entry No_]
Where
A.Amount is not NULL
Code to generate data for previous week is here (adding only where clause):
SELECT
[Entry No_],
[Customer No_],
[Posting Date],
[Description],
[Currency Code],
Trans_type = case when [Deposit]=1 then 'Deposit'
when [Imprest]=1 then 'Imprest'
else 'Other' end,
A.Amount
FROM Table1
LEFT JOIN
(
SELECT Distinct [Cust_ Ledger Entry No_],
SUM ([Amount EUR]) as 'amount'
FROM Table2
where [posting Date] < '2020-11-23'
group by [Cust_ Ledger Entry No_]
having
SUM ([Amount EUR]) <> '0'
)A
on [Entry No_] = A.[Cust_ Ledger Entry No_]
Where
A.Amount is not NULL
It would be enough to union both queries and then export to Excel and make pivot, but problem is that I need results of last 50 weeks. Is there any smart way to avoid union 50 tables and run one simple code to generate weekly report?
Thanks
it might be easier with sample, but I don't know how to paste table here..
Maybe it is true, i dont need union here, and group by would be enough, but it stills sounds difficult for me :)
Ok. Lets say table has such headers: Project | Country | date | amount
The code below returns amount for todays date
Select
Project,
SUM(amount)
From Table
Group by Project
I actually need todays date and also the results of previous weeks (What was the result on November 22 (week 47), November 15 (week 46) and so on.. total 50 weeks from todays date).
Code for previous week amount is here:
Select
Project,
SUM(amount)
From Table
Where Date < '2020.11.23'
Group by Project
So my idea was to create create 50 codes and join the results together, but i am sure it is a better way to do this. Besides i dont want to edit this query every week and add a new date for it.
So any ideas, to make my life easier?
if I have understood your requirement correctly, all you need to do is extract the week from the date e.g.
Select
Project,
datepart(week, date),
SUM(amount)
From Table
Where Date < '2020.11.23'
Group by Project, datepart(week, date)

Failed to convert NVARCHAR to INT, but I'm not trying to

I get this error:
Msg 245, Level 16, State 1, Line 5
Conversion failed when converting the nvarchar value 'L NOVAK ENTERPRISES, INC' to data type int.
I've been wrestling with this query for quite a while and just can't figure out in what place that the conversion is being attempted. Using SQL Server 2017.
DECLARE #StartDate AS DateTime
DECLARE #MfgGroupCode AS Varchar(20)
SET #StartDate='2/27/2020'
SET #MfgGroupCode = 'VOLVO_NLA'
SELECT DISTCINT
CT.No_ AS [Contact Number],
CT.Name AS [Contact Name],
UAL.Time AS [Search Date],
UAL.Param1 AS [Search Part],
CT.[E-Mail] AS [Contact Email],
CT.[Phone No_] AS [Contact Phone],
CT.[Company Name] AS [Search By Customer],
(SELECT C.Name
FROM dbo.[Customer] C
WHERE C.No_ = SL.[Sell-to Customer No_]
AND C.Name <> '') AS [Sold To Customer],
SL.[Posting Date] AS [Invoice Date],
SL.[Document No_] AS [Invoice],
SL.Quantity AS [Quantity],
SL.[Unit Price] AS [Unit Price],
SL.Amount AS [Amount],
DATEDIFF(DAY, UAL.Time, SL.[Posting Date]) AS [Interval]
FROM
dbo.[User Action Log] UAL
JOIN
dbo.[User Action Types] UAT ON UAL.[User Action ID] = UAT.ID
JOIN
dbo.[Item] I ON UAL.Param1 = I.[OEM Part Number]
JOIN
dbo.[Contact] CT ON UAL.[Contact No_] = CT.No_
LEFT OUTER JOIN
dbo.[Sales Invoice Line] SL ON UAL.Param1 = SL.[OEM Part Number]
AND SL.[Posting Date] >= #StartDate
WHERE
UAT.Name IN ('SinglePartSearch', 'MultiPartSearch')
AND UAL.[MFG Group Code] = #MfgGroupCode
AND UAL.Time >= #StartDate
AND UAL.Param3 > 0
-- AND DATEDIFF(DAY, UAL.Time, SL.[Posting Date]) < 0 -- Uncomment to see Current Searches with Past Orders
-- AND DATEDIFF(DAY, UAL.Time, SL.[Posting Date]) > -1 -- Uncomment to see Searches resulting in Future Order
AND DATEDIFF(DAY, UAL.Time, SL.[Posting Date]) IS NULL -- Uncomment to See Searches with no Order
ORDER BY
Interval DESC
Thanks to all of your help and questioning, I was able to identify that the culprit is UAL.Param3.
The User Action Log table stores a variety of different "Actions" and the parameters that are affiliated with each type of action (param1, param2, param3). For one action "RequestForAccess", the "L NOVAK" value is perfectly acceptable. For this query, we're looking at the "SinglePartSearch" and "MultiPartSearch" actions, which will only contain numeric values in UAL.Param3
I replaced this line (AND UAL.Param3 > 0) with (AND ISNUMERIC(UAL.Param3) = 1 AND UAL.Param3 <> 0) in the Where clause and it is now returning the results I hoped for.
Let me know if there is a more correct way of doing this and thank you to all who contributed!

New to SQL. Would like to convert an IF(COUNTIFS()) Excel formula to SQL code and have SQL calculate it instead of Excel

I am running SQL Server 2008 R2 (RTM).
I have a SQL query that pulls Dates, Products, Customers and Units:
select
[Transaction Date] as Date,
[SKU] as Product,
[Customer Name] as Customer,
sum(Qty) as Units
from dataset
where [Transaction Date] < '2019-03-01' and [Transaction Date] >= '2016-01-01'
group by [Transaction Date], [SKU], [Customer Name]
order by [Transaction Date]
This pulls hundreds of thousands of records and I wanted to determine if a certain transaction was a new order or reorder based on the following logic:
Reorder: That specific Customer has ordered that specific product in the last 6 months
New Order: That specific Customer hasn’t ordered that specific product in the last 6 months
For that I have this formula in Excel that seems to be working:
=IF(COUNTIFS(A$1:A1,">="&DATE(YEAR(A2),MONTH(A2)-6,DAY(A2)),C$1:C1,C2,B$1:B1,B2),"Reorder","New Order")
The formula works when I paste it individually or in a smaller dataset, but when I try to copy paste it to all 500K+ rows, Excel gives up because it loops for each calculation.
This could probably be done in SQL, but I don’t have the knowledge on how to convert this excel formula to SQL, I just started studying it.
You're doing pretty well with the start of your query there. There are three additional functions you're looking to add to your query.
The first thing you'll need is the easiest. GETDATE() simply returns the current date. You'll need that when you're comparing the current date to the transaction date.
The second function is DATEDIFF, which will give you a unit of time between two dates (months, days, years, quarters, etc). Using DATEDIFF, you can say "is this date within the last 6 months". The format for this is pretty easy. It's DATEDIFF(interval, date1, date2).
The thrid function you're looking for is CASE, which allows you to tell SQL to give you one answer if one condition is met, but a different answer if a different condition is met. For your example, you can say "if the difference in days is < 60, return 'Reorder', if not give me 'New Order'".
Putting it all together:
SELECT CASE
WHEN DATEDIFF(MONTH, [Transaction Date], GETDATE()) <= 6
THEN 'Reorder'
ELSE 'New Order'
END as ORDER_TYPE
,[Transaction Date] AS DATE
,[SKU] AS PRODUCT
,[Customer Name] AS CUSTOMER
,Qty AS UNITS
FROM DATASET
For additonal examples on CASE, take a look at this site: https://www.w3schools.com/sql/sql_ref_case.asp
For additional examples on DATEDIFF, take a look here: See the
following webpage for examples and a chance to try it out:
https://www.w3schools.com/sql/func_sqlserver_datediff.asp
SELECT CASE
WHEN Datediff(day, [transaction date], Getdate()) <= 180 THEN 'reorder'
ELSE 'Neworder'
END,
[transaction date] AS Date,
[sku] AS Product,
[customer name] AS Customer,
qty AS Units
FROM datase
If I understand correctly, you want to peak at the previous date and make a comparison. This suggests lag():
select (case when lag([Transaction Date]) over (partition by SKU, [Customer Name] order by [Transaction Date]) >
dateadd(month, -6, [Transaction Date])
then 'Reorder'
else 'New Order'
end) as Order_Type
[Transaction Date] as Date,
[SKU] as Product,
[Customer Name] as Customer,
sum(Qty) as Units
from dataset d
group by [Transaction Date], [SKU], [Customer Name];
EDIT:
In SQL Server 2008, you can emulate the LAG() using OUTER APPLY:
select (case when dprev.[Transaction Date] >
dateadd(month, -6, d.[Transaction Date])
then 'Reorder'
else 'New Order'
end) as Order_Type
d.[Transaction Date] as Date,
d.[SKU] as Product,
d.[Customer Name] as Customer,
sum(d.Qty) as Units
from dataset d outer apply
(select top (1) dprev.*
from dataset dprev
where dprev.SKU = d.SKU and
dprev.[Customer Name] = d.[Customer Name] and
dprev.[Transaction Date] < d.[Transaction Date]
order by dprev.[Transaction Date] desc
) dprev
group by d.[Transaction Date], d.[SKU], d.[Customer Name];

Meeting 2 conditions in 2 different columns

I'm trying to run a query where I need very specific conditions to be met:
Sales code is All
Item has Original Price flag set
Item has a price with no Original Price flag set that is the same as the Price with Original Price flag set
Price without Original price flag set must be created after the price with Original price flag
Currently I am using the following query to get the information I need;
select [item no_], [variant code],[unit price including vat],
[original price], [Starting Date], [Ending Date] from [Sales Price]
where [Sales Code] = 'all'
and [Ending Date] = '1753-01-01 00:00:00.000'
This is the example result:
1 means Original Price flag is set and 0 means it is not
The result I need from this query would be to only show these two:
I am assuming you are working with SQL Server as your current query syntax suggests.
If, so you can use lag() :
select sp.*
from (select sp.*,
lag([original price]) over (partition by [item no_] order by [Starting Date]) as prev_price
from [Sales Price] sp
where [Sales Code] = 'all'
) sp
where ([original price] = 1 or prev_price = 1);
let me know if you need me to explain; else its pretty straight forward.
select a.*
from (
select [item no_]
, [variant code]
,[unit price including vat]
, [original price]
, [Starting Date]
, [Ending Date]
,Column_Test = case when ( [original price] = 1 and [original price] = 0 ) and ([Starting Date]<[Ending Date]) then 1 else 0 end
from [Sales Price]
where [Sales Code] = 'all'
and [Ending Date] = '1753-01-01 00:00:00.000'
) a
where Column_Test = 1

JOIN two tables but only return rows from Table 1 that match Table 2

Good day
I have two tables I need to Join , Transfer Excise Tbl and Value Entry.
Transfer Excise Tbl: No must match the Item no in the Value Entry table. I did do a comparison for Items not in Transfer Excise that is in Value entry and found a few.
Transfer Excise Tbl:
Starting Date No_ Excise Location Location Code Unit Rate Excise Type Code Unit Of Measure Code Litre Conversion Factor
----------------------- -------------------- --------------- ------------- --------------------------------------- ---------------- -------------------- ---------------------------------------
2013-02-28 00:00:00.000 600011263 NONBOND ~DUTY PAID 2.70000000000000000000 UWNEPACK LITRES 1.33333000000000000000
2014-02-27 00:00:00.000 600011263 NONBOND ~DUTY PAID 2.87000000000000000000 UWNEPACK LITRES 1.33333000000000000000
2015-02-26 00:00:00.000 600011263 NONBOND ~DUTY PAID 3.07000000000000000000 UWNEPACK LITRES 1.33333000000000000000
2016-02-25 00:00:00.000 600011263 NONBOND ~DUTY PAID 3.31000000000000000000 UWNEPACK LITRES 1.33333000000000000000
Value Entry Table:
Item No_ Location Code Gen_ Bus_ Posting Group Invoiced Quantity
-------------------- ------------- ----------------------- ---------------------------------------
F00330 VINI EXSA -10.00000000000000000000
F00331 VINI EXSA -30.00000000000000000000
F00332 VINI EXSA -40.00000000000000000000
I want to write the query to exclude duplicates as the script below still creates duplicates. The PK is Item No and the FK is Location Code. you will see on the Transfer excise table that for each year I new unit rate was supplied for a specific Item and Location
SELECT DISTINCT a.[Starting Date],
b.[Posting Date],
b.[Item No_],
b.[Invoiced Quantity],
a.[Litre Conversion Factor],
a.[Unit Rate] ,
a.[Location Code],
a.[Excise Location],
a.[Excise Type Code],
a.[Unit Of Measure Code]
FROM [Transfer Excise Tbl] a JOIN [Spier Live$Value Entry] b
ON a.[No_] = b.[Item No_]
WHERE b.[Posting Date] > '2013-02-26 '
AND b.[Location Code] = a.[Location Code]
AND b.[Gen_ Bus_ Posting Group] IN ('LOCA','EXSA')
AND b.[Posting Date] >= a.[Starting Date]
AND b.[Invoiced Quantity] <>0
First of all, there is something wrong with your [Value Entry] table.
1) In your query you refer to [Posting Date] column, but there is no such column in your example data.
Now, if I have well understood the scenario, I think your problem is related to how you join lines from the two tables.
I get more lines than you expect because you JOIN each line in [Value Entry] with ALL lines in [Transfer Excise Tbl] with a [Starting Date] older, not only the LAST (valid) line.
To solve the problem you should pre-calc the period of validity of your [Transfer Excise Tbl] line finding the [End Date] of each line, and then you will
JOIN b.[Posting Date] BETWEEN a.[Starting Date] AND a.[End Date]
final query will be something like:
;WITH
EndDates as (-- add [End Date] to [Transfer Excise Tbl]
select t1.*, ISNULL([End Date], CONVERT(date, '9999-12-31', 121)) [End Date]
from [Transfer Excise Tbl] t1
outer apply (
select MIN([Starting Date]) [End Date]
from [Transfer Excise Tbl]
where [Starting Date] > t1.[Starting Date]
) T2
)
SELECT DISTINCT a.[Starting Date],
b.[Posting Date],
b.[Item No_],
b.[Invoiced Quantity],
a.[Litre Conversion Factor],
a.[Unit Rate] ,
a.[Location Code],
a.[Excise Location],
a.[Excise Type Code],
a.[Unit Of Measure Code]
FROM [EndDates] a JOIN [Spier Live$Value Entry] b ON a.[No_] = b.[Item No_] AND b.[Posting Date] BETWEEN a.[Starting Date] AND a.[End Date]
WHERE b.[Posting Date] > '2013-02-26 '
AND b.[Location Code] = a.[Location Code]
AND b.[Gen_ Bus_ Posting Group] IN ('LOCA','EXSA')
AND b.[Invoiced Quantity] <> 0
It should return only the number of rows you expect
I hope this helps