How i can remove results of my Query, using LAG function? - sql

First of all, srry for my bad english.
I need to calculate the iddle time of an separators group. Actualy i have the following query:
USE mydatabase
SELECT p.iddoc as SaleOrder, p.name as Client, u.username as SysUser,
CONVERT(DATETIME, o.creatdate) as CreateDate,
CONVERT(DATETIME, o.inidate) as IniDate,
CONVERT(DATETIME, o.findate) as FinalDate,
RIGHT('0' + CAST(DATEDIFF(S, (lag(o.findate, 1) OVER (ORDER BY o.findate)), o.inidate) / 3600 AS VARCHAR(2)),2) + ':'
+ RIGHT('0' + CAST(DATEDIFF(S, (lag(o.findate, 1) OVER (ORDER BY o.findate)), o.inidate) % 3600/60 AS VARCHAR(2)),2) + ':'
+ RIGHT('0' + CAST(DATEDIFF(S, (lag(o.findate, 1) OVER (ORDER BY o.findate)), o.inidate) % 60 AS VARCHAR(2)),2) as IdleTime
FROM serviceorder o
inner join user u on o.usercode = u.codusuario
inner join requests p on o.idrequest = p.codpedidocab
WHERE u.username like ('USER NAME')
and o.iduserstart is NOT NULL
and p.sit = '8'
and o.creatdate BETWEEN '2020-06-30 00:00:00' and '2020-06-30 23:59:00'
and o.inidate BETWEEN '2020-06-30 00:00:00' and '2020-06-30 23:59:00'
ORDER BY o.inidate
My problem on this query is when "o.inidate is < than a last o.findate", i need to remove the results than have "o.inidate < (lag(o.findate, 1) OVER (ORDER BY o.findate))", but i can't this because can't use the LAG on the where.
What do you suggest i do?

Window functions can be used in the select and order by clauses only. You can use a subquery instead:
SELECT *
FROM (
SELECT
p.iddoc as SaleOrder,
p.name as Client,
u.username as SysUser,
CONVERT(DATETIME, o.creatdate) as CreateDate,
CONVERT(DATETIME, o.inidate) as IniDate,
CONVERT(DATETIME, o.findate) as FinalDate,
LAG(o.findate) OVER (ORDER BY o.findate) lagFinalDate,
RIGHT('0' + CAST(DATEDIFF(S, (lag(o.findate, 1) OVER (ORDER BY o.findate)), o.inidate) / 3600 AS VARCHAR(2)),2) + ':'
+ RIGHT('0' + CAST(DATEDIFF(S, (lag(o.findate, 1) OVER (ORDER BY o.findate)), o.inidate) % 3600/60 AS VARCHAR(2)),2) + ':'
+ RIGHT('0' + CAST(DATEDIFF(S, (lag(o.findate, 1) OVER (ORDER BY o.findate)), o.inidate) % 60 AS VARCHAR(2)),2) as IdleTime
FROM serviceorder o
INNER JOIN [user] u ON o.usercode = u.codusuario
INNER JOIN requests p ON o.idrequest = p.codpedidocab
WHERE
u.username = 'USER NAME'
AND o.iduserstart is NOT NULL
AND p.sit = '8'
AND o.creatdate >= '2020-06-30'
AND o.creatdate < '2020-07-01'
AND o.inidate >= '2020-06-30'
AND o.inidate < '2020-07-01'
) t
where IniDate < lagFinalDate
Additional changes to the query:
half-open interval filters are more accurate (and easier to understand) than between
u.username like ('USER NAME') is equivalent to u.username = 'USER NAME'
user is a language keyword, hence it needs to be quoted when used as a table name

Related

How query get value where date Now in SQL Server

SELECT TOP 1000
TGL = CONVERT(DATE, TIMESTAMP), RIGHT('0' + CAST(DATEPART(hour, TimeStamp) AS VARCHAR(2)), 2) AS jam,
Nilai = MAX(NILAI)
FROM
PLC_CPress2P1
GROUP BY
CONVERT(DATE, TIMESTAMP), RIGHT('0' + CAST(DATEPART(hour, TimeStamp) AS VARCHAR(2)), 2)
ORDER BY
CONVERT(DATE, TIMESTAMP), RIGHT('0' + CAST(DATEPART(hour, TimeStamp) AS VARCHAR(2)), 2) DESC
I've tried GATEDATE() and NOW - both do not work
I think you're trying to select everthing from a table where the date equals today?
In that case, you can just do it like this:
SELECT *columns*
FROM *table_name*
WHERE *specified_date_column* = CAST(GETDATE() as date)
Here you can see all SQL Date functions: https://www.w3schools.com/sql/sql_dates.asp

Combining two rows in one select query

Hi I am having a hard time combining two records (from a single table) on a single query. The idea is, DATE_FIELD column is a date type and ColA is an integer data type.
To further illustrate my inquiry, I have attached an image below
1.) Is the raw table.
2.) Is the desired output.
P.S. The filter for DATE_FIELD is not a simple "WHERE DATE_FIELD IN" clause.
For example, I wanted to get the DATE_FIELD=12/30/2013. Then I need to get the Previous Sept DATE_FIELD also, which is 9/30/2013 programatically by using this query that I got from the web:
CASE
WHEN MONTH(DATE_FIELD) < 10
THEN
(cast(CAST((DATE_FIELD) - 1) as char(4)) + RIGHT('00' + LTRIM(09),2) + RIGHT('00' + LTRIM(30),2) AS Date))
ELSE
( cast(CAST((YEAR(DATE_FIELD)) as char(4)) + RIGHT('00' + LTRIM(09),2) + RIGHT('00' + LTRIM(30),2) AS Date))
END
Here is my current sql script (which cannot get the ColA equivalent for Previous Sept filter:
SELECT DATE_FIELD, ColA,
CASE
WHEN MONTH(DATE_FIELD) < 10
THEN
(cast(CAST((YEAR(DATE_FIELD) - 1) as char(4)) + RIGHT('00' + LTRIM(09),2) + RIGHT('00' + LTRIM(30),2) AS Date))
ELSE
( cast(CAST((YEAR(DATE_FIELD)) as char(4)) + RIGHT('00' + LTRIM(09),2) + RIGHT('00' + LTRIM(30),2) AS Date))
END AS PREVIOUS,
(
SELECT ColA
FROM TABLE_A
WHERE DATE_FIELD =
CASE
WHEN MONTH(DATE_FIELD) < 10
THEN
(cast(CAST((YEAR(DATE_FIELD) - 1) as char(4)) + RIGHT('00' + LTRIM(09),2) + RIGHT('00' + LTRIM(30),2) AS Date))
ELSE
( cast(CAST((YEAR(DATE_FIELD)) as char(4)) + RIGHT('00' + LTRIM(09),2) + RIGHT('00' + LTRIM(30),2) AS Date))
END
) AS PYE_colA
FROM TABLE_A
WHERE DATE_FIELD = '12/30/2013'
Thanks!
Do a cross join with the same table and use your CASE structure only in the where clause:
SELECT a.DATE_FIELD AS DATE_FIELD_1,
a.ColA AS ColA_1,
b.DATE_FIELD AS DATE_FIELD_2,
b.ColA AS ColA_2
FROM TABLE_A a
CROSS JOIN TABLE_A b
WHERE DATE_FIELD_1 = 'your date'
AND DATE_FIELD_2 = (
CASE
WHEN MONTH(DATE_FIELD_1) < 10
THEN
(cast(CAST((YEAR(DATE_FIELD_1) - 1) as char(4)) + RIGHT('00' + LTRIM(09),2) + RIGHT('00' + LTRIM(30),2) AS Date))
ELSE
( cast(CAST((YEAR(DATE_FIELD_1)) as char(4)) + RIGHT('00' + LTRIM(09),2) + RIGHT('00' + LTRIM(30),2) AS Date))
END)
;
Another possibility based on Thorsten Kettners remarks:
SELECT a.DATE_FIELD AS DATE_FIELD_1,
a.ColA AS ColA_1,
b.DATE_FIELD AS DATE_FIELD_2,
b.ColA AS ColA_2
FROM TABLE_A a
INNER JOIN TABLE_A b
ON b.DATE_FIELD = (
CASE
WHEN MONTH(a.DATE_FIELD) < 10
THEN
(cast(CAST((YEAR(a.DATE_FIELD) - 1) as char(4)) + RIGHT('00' + LTRIM(09),2) + RIGHT('00' + LTRIM(30),2) AS Date))
ELSE
( cast(CAST((YEAR(a.DATE_FIELD)) as char(4)) + RIGHT('00' + LTRIM(09),2) + RIGHT('00' + LTRIM(30),2) AS Date))
END)
WHERE a.DATE_FIELD = 'your date'
;

Join 2 queries with equal fields created dynamically

I have a table that i wanted to create some charts.
Basically i need to know how many registers i have in interval of 10 minutes and how many of them are already pos-processed. With this 2 queries i have the info i need, but i need they 2 in just 1 result table.
First query
SELECT
(
CAST(DATEPART(HOUR, m.Ocr_DataHora) AS NVARCHAR) +
':' +
CAST((DATEPART(MINUTE, m.Ocr_DataHora) % 6) AS NVARCHAR) +
'0'
) AS Hora,
COUNT(*) AS Movimentações
FROM
Integracao m
WHERE
m.Ocr_DataHora >= '2012-09-17 00:00:00.000'
AND m.Ocr_DataHora < '2012-09-18 00:00:00.000'
GROUP BY
DATEPART(HOUR, m.Ocr_DataHora),
(DATEPART(MINUTE, m.Ocr_DataHora) % 6)
ORDER BY
DATEPART(HOUR, m.Ocr_DataHora),
(DATEPART(MINUTE, m.Ocr_DataHora) % 6)
Second query
SELECT
(
CAST(DATEPART(HOUR, s.Ocr_DataHora) AS NVARCHAR) +
':' +
CAST((DATEPART(MINUTE, s.Ocr_DataHora) % 6) AS NVARCHAR) +
'0'
) AS Hora,
COUNT(*) AS Sucesso
FROM
Integracao s
WHERE
s.Veiculo_Modelo <> ''
AND s.Ocr_DataHora >= '2012-09-17 00:00:00.000'
AND s.Ocr_DataHora < '2012-09-18 00:00:00.000'
GROUP BY
DATEPART(HOUR, s.Ocr_DataHora),
(DATEPART(MINUTE, s.Ocr_DataHora) % 6)
How can i join them if my common field is generated dynamically?
As others have already told you, you could just use the two queries as derived tables (subselects) and join them using each one's Hora column. It doesn't matter if the column is computed in the query, it's perfectly legal to use it in a join condition.
However, I think you can get the same results more efficiently, by calculating both counts in a single query (i.e. without subqueries). Here's how you can do that:
SELECT
(
CAST(DATEPART(HOUR, m.Ocr_DataHora) AS NVARCHAR) +
':' +
CAST((DATEPART(MINUTE, m.Ocr_DataHora) % 6) AS NVARCHAR) +
'0'
) AS Hora,
COUNT(*) AS Movimentações,
COUNT(CASE WHEN s.Veiculo_Modelo <> '' THEN 1 END) AS Sucesso
FROM
Integracao m
WHERE
m.Ocr_DataHora >= '2012-09-17 00:00:00.000'
AND m.Ocr_DataHora < '2012-09-18 00:00:00.000'
GROUP BY
DATEPART(HOUR, m.Ocr_DataHora),
(DATEPART(MINUTE, m.Ocr_DataHora) % 6)
ORDER BY
DATEPART(HOUR, m.Ocr_DataHora),
(DATEPART(MINUTE, m.Ocr_DataHora) % 6)
As you can see, the query doesn't filter rows on s.Veiculo_Modelo <> ''. However, that condition is used when counting rows for the Sucesso column. The argument of the second COUNT is a CASE expression. It returns a value (arbitrarily chosen to be 1, but could be anything really) if the specified condition is met and NULL otherwise. Since COUNT omits nulls, the result will be the same as with your dedicated query calculating and returning Sucesso.
I am assuming that you want the output to be as follows:
Hora | Movimentações | Sucesso
You can use the two SQL queries as if they are table using the WITH statement as follows:
WITH
firstQuery(Hora, Movimentações) AS (<first query definition with out ORDER BY >),
secondQuery(Hora, Sucesso) AS (<second query definition with out ORDER BY >)
SELECT
f.Hora, f.Movimentações , s.Sucesso
FROM
firstQuery f
JOIN secondQuery s
ON f.Hora = s.Hora
You should be able to do this by putting them in a sub query in a from clause. The way I'm referring to has the following form:
Select A.Hora,A.Movimentações,B.Sucesso
From (*First Query*) as A
inner join (*Second Query*) as B on A.Hora = B.Hora
The end result being:
Select A.Hora,A.Movimentações,B.Sucesso
From (SELECT
(
CAST(DATEPART(HOUR, m.Ocr_DataHora) AS NVARCHAR) +
':' +
CAST((DATEPART(MINUTE, m.Ocr_DataHora) % 6) AS NVARCHAR) +
'0'
) AS Hora,
COUNT(*) AS Movimentações
FROM
Integracao m
WHERE
m.Ocr_DataHora >= '2012-09-17 00:00:00.000'
AND m.Ocr_DataHora < '2012-09-18 00:00:00.000'
GROUP BY
DATEPART(HOUR, m.Ocr_DataHora),
(DATEPART(MINUTE, m.Ocr_DataHora) % 6)
ORDER BY
DATEPART(HOUR, m.Ocr_DataHora),
(DATEPART(MINUTE, m.Ocr_DataHora) % 6)) As A
inner join (SELECT
(
CAST(DATEPART(HOUR, s.Ocr_DataHora) AS NVARCHAR) +
':' +
CAST((DATEPART(MINUTE, s.Ocr_DataHora) % 6) AS NVARCHAR) +
'0'
) AS Hora,
COUNT(*) AS Sucesso
FROM
Integracao s
WHERE
s.Veiculo_Modelo <> ''
AND s.Ocr_DataHora >= '2012-09-17 00:00:00.000'
AND s.Ocr_DataHora < '2012-09-18 00:00:00.000'
GROUP BY
DATEPART(HOUR, s.Ocr_DataHora),
(DATEPART(MINUTE, s.Ocr_DataHora) % 6)) As B on B.Hora = A.Hora

Using DatePart in line of a larger sql clause

This statement will correctly merge 2 columns ('DATE' and 'TIME'):
update AllBW1 set sUserTime =
CAST(
(
STR( YEAR( [DATE] ) ) + '/' +
STR( MONTH( [DATE] ) ) + '/' +
STR( DAY( [DATE] ) ) + ' ' +
(select DATENAME(hour, [TIME]))+ ':' +
(select DATENAME(minute, [TIME])) + ':' +
(select DATENAME(SECOND, [TIME]))
) as DATETIME)
where sUserTime is null
I'd like to refine the above so as to replace the default timezone with my own (GMT-6).
I've tried a few variations:
CAST((select DATEADD(hour, -6, DATENAME(hour, [TIME]))) as smalldatetime) + ':' +
and
(select CAST(DATEADD(hour, -6, DATENAME(hour, [TIME]))) as datetime) + ':' +
and have achieved no joy.
thx
The logfile as parsed into the SQL table by LogParser 2.2 has separate fields for Date and Time but, since both are formatted as datatime fields they end up looking like:
2012-01-04 00:00:00.000 for date (all time fields are zeroed)
2012-01-01 06:04:41.000 for time (all date field = first day of current year)
That's the reason the query is parsing each element the way it is. Thanks to Dems comment I simplified everything down. I've no doubt this can be optimized by for the volumes I'm dealing with this is adaquate:
update myTable set sUserTime =
(
DATENAME(YEAR, [DATE] ) + '/' +
DATENAME(MONTH, [DATE] ) + '/' +
DATENAME(DAY, [DATE] ) + ' ' +
DATENAME(hour, (dateadd(hh, -6, [time])))+ ':' +
DATENAME(minute, [TIME]) + ':' +
DATENAME(SECOND, [TIME])
)
where sUserTime is null

how to get sum() from alise column in SQL

I'd like the sum of TotalVisitedTime time but it is alias column so how can I gtt it?
Select CONVERT(varchar(6), DATEDIFF(second, [Start], [End])/3600)
+ ':'
+ RIGHT('0' + CONVERT(varchar(2), (DATEDIFF(second, [Start], [End]) % 3600) / 60), 2)
+ ':'
+ RIGHT('0' + CONVERT(varchar(2), DATEDIFF(second, [Start], [End]) % 60), 2) AS TotalVisitedTime
FROM [Table Name]
Note: [Start] and [End] are columns name.
SELECT SUM(TotalVisitedTime)
FROM (
-- AS PER #Alex Aza, #Andriy M
SELECT 1234 AS TotalVisitedTime
) AS OuterTable
I think it makes sense to sum up seconds and then do the conversion you are trying to do.
SELECT CONVERT(varchar(6), diff/3600)
+ ':'
+ RIGHT('0' + CONVERT(varchar(2), (diff % 3600) / 60), 2)
+ ':'
+ RIGHT('0' + CONVERT(varchar(2), diff % 60), 2) AS TotalVisitedTime
FROM
(
select sum(DATEDIFF(second, [Start], [End]) diff
from [Table Name]
) tt