Yesterday SQL Server - sql

I know very little SQL and have been asked to fix a problem in existing code. The code is PHP but the SQL causing the problem is:
$sql = "INSERT INTO Intranet.dbo.DailyBilling (Date, JobCode, SubJob, TotalTTC, TotalATTC, CompletedBillableHours, WIP, CurrencyCode, ContractValue, Invoiced, BillableTotal, BillableToday)
SELECT
Date = CONVERT(VARCHAR(10), dateadd(day,-1, getdate()), 111),
JobCode,
vwJobValueVsInvoiced.SubJob,
TotalTTC,
TotalATTC = ATTC,
CompletedBillableHours,
WIP,
vwJobValueVsInvoiced.CurrencyCode,
ContractValue,
vwJobValueVsInvoiced.Invoiced,
BillableTotal = IIF(TotalTTC <> 0,((CompletedBillableHours/TotalTTC)*ContractValue), 0),
BillableToday = IIF(TotalTTC <> 0,
IIF(Yesterday.InvoicedYesterday <> vwJobValueVsInvoiced.Invoiced,
((CompletedBillableHours/TotalTTC)*ContractValue)-vwJobValueVsInvoiced.Invoiced ,
(((CompletedBillableHours/TotalTTC)*ContractValue)-vwJobValueVsInvoiced.Invoiced)- (Yesterday.BillableTotal-Yesterday.InvoicedYesterday)),
0)
FROM
Intranet.dbo.vwJobValueVsInvoiced
LEFT JOIN
Intranet.dbo.vwCurrentRate ON vwJobValueVsInvoiced.CurrencyCode = vwCurrentRate.CurrencyCode
LEFT JOIN
(SELECT
SubJob,
BillableTotal,
BillableToday,
InvoicedYesterday = Invoiced
FROM
Intranet.dbo.DailyBilling
WHERE
Date = CONVERT(VARCHAR(10), dateadd(day,-2, getdate()), 111)) Yesterday ON vwJobValueVsInvoiced.SubJob = Yesterday.SubJob
WHERE
vwJobValueVsInvoiced.Status <> 'Complete' AND IIF(TotalTTC <> 0,((CompletedBillableHours/TotalTTC)*ContractValue)-vwJobValueVsInvoiced.Invoiced, 0) <> 0";
The tables look like this:
dbo.dailybilling
vwJobValueVSInvoice
vwCurrencyRate
SQL returns this error:
Array ( [0] => Array ( [0] => 42S22 [SQLSTATE] => 42S22 [1] => 207 [code] => 207 [2] => [Microsoft][ODBC Driver 11 for SQL Server][SQL Server]Invalid column name 'WIP'. [message] => [Microsoft][ODBC Driver 11 for SQL Server][SQL Server]Invalid column name 'WIP'. ) )
In working through it the first question I have is What is Yesterday.InvoicedYesterday? It isn’t a table I can find and is not in the outer PHP.
Second questions, why the problem with WIP? It appears in order.
Assistance much appreciated.

Yesterday is an alias given to a subquery, and InvoicedYesterday is an alias given to a column in that subquery.
LEFT JOIN (
SELECT
SubJob
, BillableTotal
, BillableToday
, InvoicedYesterday = Invoiced
FROM Intranet.dbo.DailyBilling
WHERE Date = CONVERT(varchar(10), DATEADD(DAY, -2, GETDATE()), 111)
) Yesterday ON vwJobValueVsInvoiced.SubJob = Yesterday.SubJob
All results of that subquery in the larger query will now be referenced through that alias, so all the columns of the subquery become
Yesterday.SubJob
Yesterday.BillableTotal
Yesterday.BillableToday
Yesterday.InvoicedYesterday
If you trace Yesterday.InvoicedYesterday backwards through that query it is sourced from the table Intranet.dbo.DailyBilling and from the column [Invoiced] in that table, but the subquery is filteing data using WHERE Date = CONVERT(varchar(10), DATEADD(DAY, -2, GETDATE()), 111)
If you run this
select CONVERT(varchar(10), DATEADD(DAY, -2, GETDATE()), 111)
you will see that this is "2 days ago" or "the day before yesterday" e.g. if today is 2018-10-27 the query returns '2018/10/25' (as a string, literally in that format)
I generally would not recommend use of date style 111 in your query (it is used twice). Instead I would recommend using style number 112 instead (this has no delimiter and is the safest format to use).

Like was mentioned in the previous answer, Yesterday is an alias for the subquery and invoicedYesterday is one of its columns alias.
I think the problem with the WIP column is that it belongs to the DailyBilling table but the column is not present in the select clause from the left join named with the Yesterday alias.

Related

the SQL Server Query below returns (No Columny Name) in Column 4. How do I create a Column Name in column 4

I am using the below below code, however I am running into an issue where I have been trying to rename the the column named "(No Problem Name"). I haven't figured out a solution to rename the colume "Effective Data". Currently all I can get the column to read it "No Problem Here".
SELECT DISTINCT ded.PlanYear ,ded.BenefitType ,ded.ProductID
,convert(datetime, ded.CoverageEffDate, 101) ,megp.GroupID
FROM DET_ENROLLMENT_DETAILS ded
INNER JOIN MST_EMPLOYER_GROUP_PLAN megp ON ded.ProductID = megp.ProductID
WHERE
--ded.CoverageEffDate LIKE '%2019%' ded.CoverageEffDate >= '2019-09-30' AND
ded.BenefitType = 'MEDICAL'
Change the 4th column to start with [] =
[columnname] = convert(datetime, ded.CoverageEffDate, 101)
Inside the [] you can provide the name of the colum.
Alternatively you can use AS:
convert(datetime, ded.CoverageEffDate, 101) AS ColumnName
Use 'AS name'
SELECT DISTINCT ded.PlanYear ,ded.BenefitType ,ded.ProductID
,convert(datetime, ded.CoverageEffDate, 101) AS 'convert', megp.GroupID
FROM DET_ENROLLMENT_DETAILS ded
INNER JOIN MST_EMPLOYER_GROUP_PLAN megp ON ded.ProductID = megp.ProductID
WHERE
--ded.CoverageEffDate LIKE '%2019%' ded.CoverageEffDate >= '2019-09-30' AND
ded.BenefitType = 'MEDICAL'

SQL Server : select * from table where date minus one year

How to select year-1?
This is my code:
select
a.*
from
(select
met_men, kli_kod, pre_kod, galutinis, savik_group, marza,
KLR_KOD, KLI_POZ1, KLI_POZ2, KLI_POZ3, KLG_KOD, PRE_RUS,
PRE_POZ1, PRE_POZ2, PRE_POZ3, PRE_POZ4, PRE_POZ5, PRE_POZ6,
did_dat, savi_suproc, marza_suproc, pre_ska dbo.SVF_View_10) AS a
left outer join
(select
pre_kod, kli_kod, met_men, did_dat
from
dbo.SVF_View_10_sum
where
dateadd(year, -1, 'did_dat')) as b on a.kli_kod = b.kli_kod
and a.pre_kod = b.pre_kod
and a.did_dat = b.did_dat
This error occurs on the line where DATEADD(year, -1, 'did_dat')) as b:
Msg 4145, Level 15, State 1, Line 6
An expression of non-boolean type specified in a context where a condition is expected, near ')'.
Please help me
the required data: order date, id, quantity, orderdate-1 year, quantity. It is necessary to compare the quantity sold for this year and for the last year
You give column name in single quote dateadd(year, -1, 'did_dat') which is no need here change into dateadd(year, -1, did_dat) and when you use where clause need to give comparison operation in where clause.
so changed into
where did_dat <= dateadd(year, -1, did_dat)
but it doesn't make any sense because query should be execute on previous year against current date like
where did_dat <= dateadd(year, -1, GETDATE())
I suspect what you want is:
select . . .
from dbo.SVF_View_10 v left outer join
dbo.SVF_View_10_sum vs
on v.kli_kod = vs.kli_kod and a.pre_kod = b.pre_kod and
v.did_dat = dateadd(year, -1, vs.did_dat);
Notes:
Subqueries are not necessary for this query. I think they just make the query harder to write and to read.
Use table aliases that are abbreviations for the table names.
You have a date calculation in the where clause rather than a boolean expression. That is causing your error.
The date expression has a string for the third argument. The would be your next error. Strings do not refer to column names.
I am speculating that you want the tables joined on that date expression.
Try This :-
SELECT a.*
FROM
(
SELECT met_men,kli_kod,pre_kod,galutinis,savik_group,marza,KLR_KOD,LI_POZ1,
KLI_POZ2,KLI_POZ3,KLG_KOD,PRE_RUS,PRE_POZ1,PRE_POZ2,PRE_POZ3,PRE_POZ4,
PRE_POZ5,PRE_POZ6,did_dat,savi_suproc,marza_suproc,pre_ska
FROM SVF_View_10_sum
) AS a
LEFT OUTER JOIN
(
SELECT pre_kod,kli_kod,met_men,did_dat
FROM dbo.SVF_View_10_sum
WHERE did_dat = DATEADD(YEAR, -1, did_dat)
) AS b
ON a.kli_kod = b.kli_kod AND a.pre_kod = b.pre_kod AND a.did_dat = b.did_dat;

joining three select statements

I create reports in SQL Server Report Builder. I hope anyone can help me in this case. My query shows me an error if I add a third inner join
How can I add a third select statement?
You need to update the final GROUP BY clause. Including the full name in the SELECT clause requires the full name in the GROUP BY.
As a rule of thumb: When using GROUP BY every field used in the SELECT clause, that isn't combined with an aggregate function, must appear.
Select
SUM(cast(Units as int)) as CounterName,
left(Name,4) as Machine,
Name as WasteLabel
from
Trouble
inner join tsystem ON Trouble.systemid = tsystem.id
where
Name not in ('Aus', 'An', 'Produced')
and IntervalDateWeek >= dateadd(wk, datediff(wk, 0, getdate()) - 2, 0)
and IntervalDateWeek <= dateadd(wk, datediff(wk, 0, getdate())-1, 0)
and left(Name, 4) in (Select name from tSystem
where
ID in
(
Select
systemid
from
tsystemviewSystemwhere
WHERE
SystemViewID = 4)
)
group by
Name
I suspect your query could be improved. Adding clear sample data and expected output will help here.

SQL Server DATE conversion error

Here is my query:
SELECT
*
FROM
(SELECT
A.Name, AP.PropertyName, APV.Value AS [PropertyValue],
CONVERT(DATETIME, APV.VALUE, 101) AS [DateValue]
FROM dbo.Account AS A
JOIN dbo.AccountProperty AS AP ON AP.AccountTypeId = A.AccountTypeId
JOIN dbo.AccountPropertyValue AS APV ON APV.AccountPropertyId = APV.AccountPropertyId
AND APV.AccountId = A.AccountId
WHERE
A.AccountTypeId = '19602AEF-27B2-46E6-A068-7E8C18B0DD75' --VENDOR
AND AP.PropertyName LIKE '%DATE%'
AND ISDATE(APV.Value) = 1
AND LEN(SUBSTRING( REVERSE(APV.Value), 0 , CHARINDEX( '/', REVERSE(APV.Value)))) = 4 --ENSURE 4 digit year
) AS APV
WHERE
APV.DateValue < GETDATE()
It results in the following error:
Conversion failed when converting date and/or time from character string.
If you comment out the WHERE APV.DateValue < GETDATE() clause then there is no error and I get the 300+ rows. When I enable the WHERE clause I get the error.
So you are going to tell me my data is jacked up right? Well that's what I thought, so I tried to figure out where the problem in the data was, so I started using TOP() to isolate the location. Problem was once I use the TOP() function the error went away, I only have 2000 rows of data to begin with. So I put a ridiculous TOP(99999999) on the inner SELECT and now the entire query works.
The inner SELECT returns the same number of rows with or without the TOP().
WHY???
FYI, this is SQL that works:
SELECT
*
FROM
(SELECT TOP(99999999)
A.Name, AP.PropertyName, APV.Value AS [PropertyValue],
CONVERT(DATETIME, APV.VALUE, 101) AS [DateValue]
FROM dbo.Account AS A
JOIN dbo.AccountProperty AS AP ON AP.AccountTypeId = A.AccountTypeId
JOIN dbo.AccountPropertyValue AS APV ON APV.AccountPropertyId = APV.AccountPropertyId
AND APV.AccountId = A.AccountId
WHERE
A.AccountTypeId = '19602AEF-27B2-46E6-A068-7E8C18B0DD75' --VENDOR
AND AP.PropertyName LIKE '%DATE%'
AND ISDATE(APV.Value) = 1
AND LEN(SUBSTRING(REVERSE(APV.Value), 0 , CHARINDEX( '/', REVERSE(APV.Value)))) = 4
) AS APV
WHERE
APV.DateValue < GETDATE()
The problem that you are facing is that SQL Server can evaluate the expressions at any time during the query processing -- even before the WHERE clause gets evaluated. This can be a big benefit for performance. But, the consequence is that errors can be generated by rows not in the final result set. (This is true of divide-by-zero as well as conversion errors.)
Fortunately, SQL Server has a work-around for the conversion problem. Use try_convert():
TRY_CONVERT( DATETIME, APV.VALUE, 101) AS [DateValue]
This returns NULL rather than an error if there is a problem.
The reason why some versions work and others don't is because of the order of execution. There really isn't a way to predict what does and does not work -- and it could change if the execution plan for the query changes for other reasons (such as table statistics). Hence, use try_convert().
My guess is that your date is such that APV.VALUE contains also data that cannot be converted into a date, and should be filtered out using the other criteria?
Since SQL Server can decide to limit the data first using the criteria you have given:
APV.DateValue < CONVERT( DATETIME, GETDATE(),101)
And if there is data that cannot be converted into the date, then you will get the error.
To make it more clear, this is what is being filtered:
CONVERT( DATETIME, APV.VALUE, 101) AS [DateValue]
And if there is any data that cannot be converted into a date using 101 format, the filter using getdate() will fail, even if the row would not be included in the final result set for example because AP.PropertyName does not contain DATE.
Since you're using SQL Server 2012, using try_convert instead of convert should fix your problem
And why it works with top? In that case SQL Server cannot use the criteria from the outer query, because then the result might change, because it might affect the number of rows returned by top
Because number of records in the table < 999..99. And regarding the error it seems like SQL engine evaluates the WHERE clause after converting to date so you can try this:
SELECT *
FROM (
SELECT A.Name
, AP.PropertyName
, APV.Value AS [PropertyValue]
,
CASE
WHEN SDATE(APV.Value) = 1
THEN CONVERT( DATETIME, APV.VALUE, 101)
ELSE NULL
END AS [DateValue]
FROM dbo.Account AS A
JOIN dbo.AccountProperty AS AP
ON AP.AccountTypeId = A.AccountTypeId
JOIN dbo.AccountPropertyValue AS APV
ON APV.AccountPropertyId = APV.AccountPropertyId
AND APV.AccountId = A.AccountId
WHERE A.AccountTypeId = '19602AEF-27B2-46E6-A068-7E8C18B0DD75' --VENDOR
AND AP.PropertyName LIKE '%DATE%'
AND LEN( SUBSTRING( REVERSE(APV.Value), 0 , CHARINDEX( '/', REVERSE(APV.Value)))) = 4 --ENSURE 4 digit year
) AS APV
WHERE APV.DateValue IS NOT NULL AND APV.DateValue < GETDATE()

Get date from substring in where clause of a sql select *EDITED*

I have a date stored within a text field with other text. Why didn't they just put this in a date field? I have no idea, but I do not have the power to change it now. Elsewhere in the code, I am doing this to get the records where this date is in a certain range. It works fine.
For Each i As InventoryItem In inventoryList
index = i.Notes.IndexOf("on {") + 4
scanned_dt = i.Notes.Substring(index, i.Notes.Length - index - 1)
If Date.Parse(scanned_dt) >= startDate And Date.Parse(scanned_dt) <= endDate Then
...
I am now trying to get a total of items for a certain date range.
This sql statement works to get the total for all dates. How can I update the Where clause to only count the items where i.Notes contains a date between startDate and endDate
Dim sql As String = "Select COUNT(inv_PartNum) from lester.inventory i join lester.vendor v on v.vendor_ID = i.vendor_ID Where v.vendor_Name = '" + vendorName + "' AND i.inv_Desc LIKE '%" + size + "%'"
*EDITED*
I came up with this sql select statement:
SELECT COUNT(i.inv_PartNum) FROM cdms.lester.inventory AS I
join CDMS.lester.vendor AS v on v.vendor_ID = i.vendor_ID Where v.vendor_Name = 'JVE-285'
AND CONVERT(DATETIME,
SUBSTRING(i.inv_Notes, CharIndex('on {', i.inv_Notes)+4, len(i.inv_Notes)-(CharIndex('on {', i.inv_Notes) + 4)
),101) BETWEEN '01-01-2011' AND '04-04-2011'
But I am getting this error:
The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value.
In trying to figure it out I created the following sql select statement:
SELECT * FROM (
SELECT i.inv_Notes,
CONVERT(DATETIME,SUBSTRING(i.inv_Notes, CharIndex('on {',i.inv_Notes)+4,LEN(i.inv_Notes)-(CharIndex('on {', i.inv_Notes) + 4)),101) AS d
FROM cdms.lester.inventory AS i
join CDMS.lester.vendor AS v ON v.vendor_ID = i.vendor_ID WHERE v.vendor_Name = 'JVE-285') AS s
My inv_Notes column contains a string like "Assigned to Tool Trailer {JVE-285} on {4/8/2011}"
When I run the query as shown above, I get my inv_Notes column along with the date column. The dates all show in this format "2011-04-08 00:00:00.000" and no errors are thrown.
However as soon as I add a WHERE clause, I get the error: The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value.
I've tried formatting the date every which way, but always get the error...
WHERE s.d > CONVERT(DATETIME, '2011-1-1', 101)
WHERE s.d < GetDate()
WHERE s.d > '20110101'
WHERE s.d >= '2011-01-01'
WHERE s.d >= '01-01-2011'
WHERE s.d > '01/01/2011'
EDIT
I've also tried
WHERE s.d IS NOT NULL
and get the same error. This obviously isn't working the way I think it's working b/c at the point of the WHERE, the conversion should have already successfully happened.
SOLUTION
Got this working
SELECT * FROM (
SELECT i.inv_Notes,
SUBSTRING(i.inv_Notes, CharIndex('} on {',i.inv_Notes)+6,LEN(i.inv_Notes)-(CharIndex('} on {', i.inv_Notes) + 6))
AS d
FROM cdms.lester.inventory AS i
join CDMS.lester.vendor AS v ON v.vendor_ID = i.vendor_ID WHERE v.vendor_Name = 'JVE-285') AS s
WHERE PARSENAME(REPLACE(s.d, '/', '.'), 1)+
RIGHT('00'+PARSENAME(REPLACE(s.d, '/', '.'), 3),2)+
RIGHT('00'+PARSENAME(REPLACE(s.d, '/', '.'),2),2) BETWEEN '20110407' AND '20110409'
I tried to cast that to int and do an integer comparison but then I get an error. Figured out that the problem was that some of the inv_Notes fields contain data like "Item Added {3/11/2011}" None of those meet the conditions for the inner select, so in my mind if it's not selected in the inner select, it shouldn't be a problem for the condition of the outer select. However, it was trying to cast 2011{311 to int and throwing an error. I'm sure it was trying to cast that to date and that's why I had the previous problems.
Try adding something similar to this WHERE clause into your statement:
WHERE CAST(SUBSTRING(Notes, CHARINDEX(Notes, 'on {') + 4, Length?) AS Date) BETWEEN StartDate And EndDate
The idea been that you extract the relevant part of the string by combining the SubString and CharIndex methods, and then convert this expression to a date format so that it can be used with the Between Operator.
Best of Luck
Part 2 Update:
As you have been able to select the date but not use it in the where clause, I suggest using it as a select statement and then wrapping this in another statement e.g:
SELECT *
FROM
(SELECT CAST(SUBSTRING(Notes, CHARINDEX(Notes, 'on {') + 4, Length?) AS Date) AS dtmNotes)
WHERE dtmNotes BETWEEN Start And End
This is just to illustrate, but include the whole of your first select statement in the wrapping.
Try this...
assuming that the table with the embedded date is called InventoryList and the column is called inv_Notes
SELECT *
FROM InventoryList i
WHERE
CAST(
substring(
i.inv_Notes,
patindex('%on {%',i.inv_Notes) +4,
patindex('%[0-9][0-9][0-9][0-9]}%',i.inv_Notes)-patindex('%on {%',i.inv_Notes)
) as Datetime)
BETWEEN '12/1/2011' AND '12/23/2011
EDIT: More restrictive looking for a "9/9999}" pattern
SELECT *
FROM InventoryList i
WHERE
CAST(
substring(
i.inv_Notes,
patindex('%on {%',i.inv_Notes) +4,
patindex('%[0-9]/[0-9][0-9][0-9][0-9]}%',i.inv_Notes)-patindex('%on {%',i.inv_Notes)
) as Datetime)
BETWEEN '12/1/2011' AND '12/23/2011