Hi I am pretty new to sql and I keep getting the sql default value 1900-01-01 00:00:00.000. I just want the field to be empty. I thought if I put '' the empty string it would use that instead of the default value. I commented the line where I think the problem is. I have tried other ways like ISNULL and Convert but that does not work. Thanks in advance and if you can explain how the default date works and how to override it that would be much appreciated.
DECLARE #custAccount nvarchar(20)
SET #custAccount='CUS07869'
SELECT 'SM' as [Origin]
,'SN' as [Action Code]
,ST.PurchOrderFormNum as [Order Number]
,SL.ITEMID AS [LINE ITEM]
,SL.QTYORDERED as [Quantity]
,S.SHIPMENTDATE as [Action Date]
,S.TRACKINGNUMBER as [TRACKING]
,ISNULL(S.SHIPMENTDATE, '') as [DATE_SHIPPED]
,S.SHIPMETHOD as [Carrier]
FROM SalesTable ST
INNER JOIN GBP_Shipping S
ON ST.SalesId=S.SalesId AND ST.DataAreaId=S.DataAreaId
INNER JOIN SalesLine SL
ON ST.SalesId=SL.SalesId AND ST.DataAreaId=SL.DataAreaId
WHERE ST.CUSTACCOUNT=#custAccount
AND S.SHIPMENTDATE = convert(varchar, getdate(), 111)
AND ST.salestype!=4
UNION
SELECT 'SM' as [Origin]
,'AN' as [Action Code]
,ST.PurchOrderFormNum as [Order Number]
,SL.ITEMID AS [LINE ITEM]
,SL.QTYORDERED as [Quantity]
,replace(convert(varchar, getdate(), 111), '/', '') as [Action Date]
,'' as [TRACKING]
,'' as [DATE_SHIPPED] --I think this is the problem
,'' as [Carrier]
FROM SalesTable ST
INNER JOIN SalesLine SL
ON ST.SalesId=SL.SalesId AND ST.DataAreaId=SL.DataAreaId
WHERE ST.CUSTACCOUNT=#custAccount
AND ST.CREATEDDATE = convert(varchar, getdate(), 111)
In the first part of your union sets the type of the data in the column.
try
,case when S.SHIPMENTDATE is null then ''
else Convert(VarChar(10),S.SHIPMENTDATE)
end as DATE_SHIPPED
instead
of
,ISNULL(S.SHIPMENTDATE, '') as [DATE_SHIPPED]
SQL does not have an "empty" default date -- you have to set something there. Under the hood they are stored as a binary value, and a binary value of 0 gets transalted to something; here, I'd guess you are using smalldatetime, and I'm reasonably sure 0 = Jan 1, 1900. (Datetime of 0 gets you something in 1753, when the Gregorian calendar officialy started. I'm not sure what coin they flipped for the date/time datatypes new to SQL 2008.)
If you want "no date", you'll probably have to use NULL values, and check for them wherever relevant with the isnull function. Irritating, perhaps, but IMHO it's one of the most legit uses of NULL values in SQL.
Related
How can I use Sum, Cast and Partition by functions together?
I get error.
Conversion failed when converting the nvarchar value '693.41' to data
type int."
I tried this
SUM(CAST([total price] AS INT)) OVER (PARTITION BY (ProjectType)) as TotalPriceV2
Full query is at the below.
SELECT
ID,
[Project Manager],
Job#,
[Date],
[Job Type],
first_value([Job Name]) OVER (PARTITION BY value_partition ORDER BY ID) CustomerGroup, Value_Partition
Customer,
[Sales Rep1],
DeliveryType,
ProjectType,
[Item Price],
[Service Price],
[Total Price],
SUM(CAST([total price] AS INT)) OVER (PARTITION BY (ProjectType)) as TotalPriceV2
FROM (
SELECT
ID,
[Project Manager], Job#, [Date], [Job Type], [Job Name],Customer,[Sales Rep1],DeliveryType,ProjectType,[Item Price],[Service Price],[Total Price],
SUM(CASE WHEN [JOB NAME] IS NULL THEN 0 ELSE 1 END) OVER (ORDER BY ID) AS Value_Partition
FROM Testing2
WHERE
[Date] IS NOT NULL AND
([Date] NOT LIKE '0' OR JOB# NOT LIKE '0' OR [JOB TYPE] NOT LIKE '0')
AND [Project Manager] NOT LIKE 'ITEM / SERVICE'
) AS X
First, identify the rows that have problems. You are converting to an int, so:
select price
from Testing2
where try_convert(int, price) is null and price is not null;
At least some of the values will have decimal points (as in your example). To see if this is the only problem, I would suggest converting to a decimal next:
select price
from Testing2
where try_convert(decimal(20, 4), price) is null and price is not null;
If this returns nothing, you are set. If not, you will need to figure out how to address these exceptions.
Then, I would phrase the calculation using decimals and not floats:
SUM(TRY_CAST([total price] AS DECIMAL(20, 4))) OVER (PARTITION BY (ProjectType)) as TotalPriceV2
Monetary amounts should generally be represented using fixed-point values rather than approximate floating point values. The issue with floating point values is that information may be lost. Consider this example with reals:
select cast(1000000 as real) + cast(0.01 as real),
cast(1000000 as decimal(20, 4)) + cast(0.01 as decimal(20, 4))
Integer will not have decimal values, and it will throw an error.
If I use this, similar to the example you have.
Declare #val nvarchar(10) = '10.24'
select cast (#val as int)
I get this following error.
Msg 245, Level 16, State 1, Line 3
Conversion failed when converting the nvarchar value '10.24' to data type int.
Now to avoid this error, I can round the digit to 0 decimal places and convert as Int. Also, I would recommend to use Try_Cast to avoid any cases of actual nvarchar values(it would convert it to null) if you are using sql server 2012 or more.
Declare #val nvarchar(10) = '10.24'
select Try_cast (round(#val,0) as int) as valuen
Output, I think this will work in your sum function.
valuen
10
Why don't you cast it in inner query with decimal(16,9) instead of int
SELECT
ID,
[Project Manager],
Job#,
[Date],
[Job Type],
first_value([Job Name]) OVER (PARTITION BY value_partition ORDER BY ID) CustomerGroup, Value_Partition
Customer,
[Sales Rep1],
DeliveryType,
ProjectType,
[Item Price],
[Service Price],
[Total Price],
SUM([total price]) OVER (PARTITION BY (ProjectType)) as TotalPriceV2
FROM (
SELECT
ID,
[Project Manager], Job#, [Date], [Job Type], [Job Name],Customer,[Sales Rep1],DeliveryType,ProjectType,[Item Price],[Service Price],cast([Total Price] as decimal(16,9)) as [Total Price],
SUM(CASE WHEN [JOB NAME] IS NULL THEN 0 ELSE 1 END) OVER (ORDER BY ID) AS Value_Partition
FROM Testing2
WHERE
[Date] IS NOT NULL AND
([Date] NOT LIKE '0' OR JOB# NOT LIKE '0' OR [JOB TYPE] NOT LIKE '0')
AND [Project Manager] NOT LIKE 'ITEM / SERVICE'
) AS X
If you have a combination of string and number as your column value and you want to sum up the number. For SQL Server 2012+ you can use TRY_CAST or TRY_CONVERT to avoid any casting errors.
TRY_CAST (Transact-SQL)
In your scenario, you are not using proper data type for casting, you have values like 693.41 which can't be casted to INT, instead you should use DECIMAL datatype.
One more suggestion, instead of using NOT LIKE, better use <> in SQL Server like following.
Change
([Date] NOT LIKE '0' OR JOB# NOT LIKE '0' OR [JOB TYPE] NOT LIKE '0')
to
([Date] <> '0' OR JOB# <> '0' OR [JOB TYPE] <> '0')
One possible solution is to firstly convert the nvarchar value to decimal and then to integer:
CAST(CAST([total price] AS FLOAT) AS INT)
However, in this way the decimal part is lost if it matters to you.
Could you take a look at the query below please? I tried to convert my access table into a SQL query with very little knowledge (for now).
The last line seems to be wrong when I execute it.
USE [idb_datastore]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[idb_dataSTORESQLTesting]
AS
IF OBJECT_ID( 'idb_datastore.dbo.[Testing]','U' ) IS NOT NULL
DROP TABLE idb_datastore.dbo.[Testing];
SELECT dbo.REC_HDR.F91 AS [PO Number],
hd.F1032 AS [Trs Number],
hd.F76 AS [Order Date],
hd.F27 AS [Vendor ID],
hd.F334 AS [Vendor Name],
hd.F1246 AS [Delivery Date],
hd.F1127 AS [Operator Short Name],
hd.F1068 AS State,
hd.F1067 AS Status
FROM SMSSERVER01.STORESQL.dbo.REC_HDR hd
WHERE hd.F91 Is Not Null AND hd.F76 >= Convert(datetime, ’2017/01/01’ ) AND
hd.F1068 NOT like ’Voided’
Here
SQL datetime format is yyyy-mm-dd hh:mm:ss
change the final line to this
Convert(datetime, '2017-01-01' )
Change the where sentence to this
WHERE hd.F91 Is Not Null
AND hd.F76 >= CONVERT(DATETIME, '03/13/2013', 101)
AND hd.F1068 NOT like '%Voided%'
I'm having some trouble with syntax.
First, I'd like to convert a date from this format:
2014-12-18 21:49:54.047
To this format:
20141218
I can do this just fine using this select statement:
SELECT F253 = CONVERT (VARCHAR (20), F253, 112)
FROM SAL_HDR
My problem is with the syntax. How do I put that select statement inside of a select statement with a bunch of other lines? I can't seem to make it work right. I have commented out the line in question. How do I write that line into the larger select statement?
SELECT
SAL_HDR.F253 AS [Transaction Date],
/*F253 = CONVERT (VARCHAR (20), F253, 112)*/
SAL_HDR.F1036 AS [Transaction Time],
SAL_HDR.F1032 AS [Transaction #],
FROM SAL_HDR
Just add it in as an expression:
SELECT CONVERT(VARCHAR(20), SAL_HDR.F253, 112) AS [Transaction Date],
SAL_HDR.F1036 AS [Transaction Time],
SAL_HDR.F1032 AS [Transaction #]
FROM SAL_HDR;
Alternatively, you can use the syntax:
SELECT [Transaction Date] = CONVERT(VARCHAR(20), SAL_HDR.F253, 112),
[Transaction Time] = SAL_HDR.F1036,
[Transaction #] = SAL_HDR.F1032
FROM SAL_HDR;
I personally prefer the first version, because I find that the second is too close to variable assignment.
I need to push data from a SQL table to an intermediate table in JDE. I am having issues with NULLS not being passed as blanks. How can I replace any NULL values with blanks into JDE.
This is my statement to update my SQLDB:
Insert into AP_InvoiceHeader
(DocID,[Vendor Name],[Vendor No],[Invoice Number],[Invoice Date],[PO Number],[Invoice Amount],MVRUploadDate,DocName)
values ({sys DocID},'{doc Vendor Name}','{doc Vendor No}','{doc Invoice Number}','{doc Invoice Date}','{doc PO Number}','{doc Invoice Amount}',GETDATE(),(select DocName from document where Docid={sys DocID}))
With this statement, if there isn't a value to pass, it shows up as NULL in SQL. Would it be better to do a NULL to blank conversion into my SQLDB or should it be done when I update the intermediate table?
This is my statement that selects from my SQLDB and inserts it into the intermediate JDE table. I know what I want to do but, I am not sure how to write it. I would like to say, if [PO Number]=NULL change it to blank. Is there a way that it can check for any NULLS and replace all NULLS with blanks?
INSERT INTO [MyJDE_VENDOR].[PS_DEV].[TESTDTA].[F55METAA] ([MVMLNM],[MVAN8],[MVVR01],[MVVINV],[MVDIVJ],[MVAG],[MVTRDJ],[MVRMK3],[MV55MV],[MVUMEMO1])
SELECT [Vendor Name],[Vendor No],[PO Number],[Invoice Number],cast('1'+ RIGHT(CAST(YEAR(cast([Invoice Date] as date)) AS CHAR(4)),2) + RIGHT('000' + CAST(DATEPART(dy, cast([Invoice Date] as date)) AS varchar(3)),3) as int) as [Invoice Date],[Invoice Amount]*100,cast('1'+ RIGHT(CAST(YEAR(cast([MVRUploadDate] as date)) AS CHAR(4)),2) + RIGHT('000' + CAST(DATEPART(dy, cast([MVRUploadDate] as date)) AS varchar(3)),3) as int) as [MVRUploadDate],[ProcessedFlag],[DocID],[DocName]
FROM [MyDataBase].[dbo].[AP_InvoiceHeader] WHERE DocID ={sys DocID}
The standard SQL function is coalesce(). It is a bit unclear which fields you want this for:
INSERT INTO [MyJDE_VENDOR].[PS_DEV].[TESTDTA].[F55METAA] ([MVMLNM],[MVAN8],[MVVR01],[MVVINV],[MVDIVJ],[MVAG],[MVTRDJ],[MVRMK3],[MV55MV],[MVUMEMO1])
SELECT coalesce([Vendor Name], ''),
coalesce([Vendor No], ''),
coalesce([PO Number], ''),
coalesce([Invoice Number], '')
coalesce(cast('1'+ RIGHT(CAST(YEAR(cast([Invoice Date] as date)) AS CHAR(4)),2) + RIGHT('000' + CAST(DATEPART(dy, cast([Invoice Date] as date)) AS varchar(3)),3) as int) as [Invoice Date],[Invoice Amount]*100,cast('1'+ RIGHT(CAST(YEAR(cast([MVRUploadDate] as date)) AS CHAR(4)),2) + RIGHT('000' + CAST(DATEPART(dy, cast([MVRUploadDate] as date)) AS varchar(3)),3) as int) , '') as [MVRUploadDate],
coalesce([ProcessedFlag], ''),
coalesce([DocID], ''),
coalesce([DocName], '')
FROM [MyDataBase].[dbo].[AP_InvoiceHeader]
WHERE DocID ={sys DocID}
In MS SQL SERVER, if you are specifically targeting nulls then you can use the isnull function.
isnull(column,'')
I am using SQL Server 2005 and trying to write a query where I want to retrieve payments for a given month. I currently have:
select sum(p1.paymentamount) as subtotal,
CONVERT(char(10), p1.paymentdate, 103) as paymentdate
from tblpayment p1
where 1=1
and p1.paymentdate >= #fromdate
and p1.paymentdate <= #todate
group by p1.paymentdate
order by p1.paymentdate
Schema:
CREATE TABLE [dbo].[tblPayment]
(
[paymentid] [int] IDENTITY(1,1) NOT NULL,
[userid] [int] NULL ,
[paymentdate] [datetime] NOT NULL,
[paymentamount] [int] NULL,
[paymenttype] [varchar](50) NULL,
[paymentnotes] [varchar](200) NULL,
[paymentcurrency] [nchar](10) NULL
)
This query gives me what I want but it doesnt give me the dates where no payments were made. What I want is a query that gives me all days even if there were no payments made on that day and jut shows the subtotal as 0 for that day.
There is another catch. The currency of payments is different. So how can I have another column in the query that gives me eurototal and sterlingtotal based on #currency parameter passed in ? Assuming there is a column in the table for "paymentcurrency"
You have to work backwards. In order to get rows for dates that don't exist, you need to outer join them to rows that do have those dates. In order to outer join, you need to have a sequence to join to. Since you don't have a sequence, you need to create one.
To create that sequence, you have two options:
Create a static date sequence and store it in a permanent table (Larry's answer); or
Use an existing numeric sequence (such as spt_values) to create one on the fly.
Let's assume you want the flexibility of the second approach. Here's a common snippet I use for things like that:
SELECT DATEADD(DAY, v.number, #fromdate)
FROM master.dbo.spt_values v
WHERE v.type = 'P'
AND v.number <= DATEDIFF(DAY, #fromdate, #todate)
Now just toss that in a CTE and join it:
WITH Dates_CTE (dt) AS
(
-- // Paste the snippet above in here
)
SELECT d.dt AS paymentdate, ISNULL(SUM(p.paymentamount), 0) AS subtotal
FROM Dates_CTE d
LEFT JOIN tblpayment p
ON p.paymentdate = d.dt
GROUP BY d.dt
ORDER BY d.dt
(Update: I left out the WHERE clause in the main query because it's technically handled by the the join, but in some instances you might get better performance by leaving it in)
As for the currency conversion, look up the syntax for PIVOT.
Update on PIVOT: You should be able to just enclose that entire query in parentheses, then go:
SELECT paymentdate, [Euro] AS euroamount, [Pound] as poundamount
FROM
(
-- // Insert the full query from above in here
) p
PIVOT
(
SUM(subtotal)
FOR paymentcurrency IN ([Euro], [Pound])
) AS pvt
Hard to verify without knowing exactly what kind of data is in there, but try that as a starting point.
If there are no dummy records in tblPayment for the dates without any payment, those dates will not appear in a query that selects only from tblPayment.
I handle this by creating a separate table with nothing but dates in it (one row per date), checking to make sure that I have all the dates to cover my query, and then LEFT JOINing my main table (in this case tblPayment) on the date table:
SELECT * FROM tblPayment LEFT OUTER JOIN tblDates
ON tblPayment.PaymentDate = tblDates.PossibleDate
This basic idea can be enhanced with GROUP BY to get the summary figures you want.
Here is one approach
Create the following function:
CREATE FUNCTION [dbo].[DateTable] (#StartDate DATETIME, #endDate DATETIME)
RETURNS #Itms TABLE
(
TheDate DATETIME
)
AS
BEGIN
DECLARE #theDate DATETIME
SET #TheDate = #StartDate
WHILE #TheDate <= #endDate
BEGIN
INSERT #Itms VALUES (#theDate)
SET #TheDate =dateAdd(d,1,#theDate)
END
RETURN
END;
Then here is a query that should do what you want
select sum(p1.paymentamount) as subtotal,
CONVERT(char(10), p1.paymentdate, 103) as paymentdate
from
(select * from tblpayment p1
where 1=1
and p1.paymentdate >= #fromDate
and p1.paymentdate <= #toDate
union
select theDate as paymentDate,0 as paymentAmount
from dbo.dateTable (#fromDate,#toDate)
) p1
group by p1.paymentdate
try something like this perhaps?
select sum(p1.paymentamount) as subtotal,
CASE WHEN (CONVERT(char(10), p1.paymentdate, 103) = 0) THEN 'No Sale'
ELSE
CONVERT(char(10), p1.paymentdate, 103)
END as paymentdate
FROM tblpayment
where paymentdate BETWEEN #fromdate and #todate
As mentioned before you have to use a separate table (temp or permanent). The currency conversion can be done using a CASE statement. Check out the below (I made up the conversion factors ;)
declare #dates table (dateitem datetime)
declare #lower datetime
declare #upper datetime
set #lower = '12/1/9'
set #upper = '12/31/9'
while #lower <= #upper
begin
insert into #dates values (#lower)
set #lower = dateadd(day, 1, #lower)
end
select dateitem, paymentcurrency,
paymentindollars = case paymentcurrency when 'dollars' then total when 'euro' then total * 1.7 else 0 end,
paymentineuros = case paymentcurrency when 'dollars' then total * 0.73 when 'euro' then total else 0 end
from
(select dateitem, paymentcurrency, sum(paymentamount) as total
from #dates DT left join tblpayment on DT.dateitem = tblpayment.paymentdate group by dateitem, paymentcurrency
) IQ order by dateitem
Caveats to watch out for:
your payementdate might have times in
it that you will have to remove
(through casting) for the join/grouping to work properly
for the conversions to work right you have to separate the differnt currency types, you could always wrap them in another sql to get a grand total for the day
currency conversion is usually only good for the day so applying a general conversion against a period of time is not going to give you good financial results, only decent ballpark figures (ie don't try and file it on your taxes ;)
Hope that helps a bit.