List values with MaxDate - sql

Im trying to create ie query to show itens with MAX DATE, but I donĀ“t know how !
Follow the script and result:
Select
results.severity As "Count_severity",
tasks.name As task,
results.host,
to_timestamp(results.date)::date
From
tasks Inner Join
results On results.task = tasks.id
Where
tasks.name Like '%CORP 0%' And
results.severity >= 7 And
results.qod > 70
I need to show only tasks with the last date of each one.
Can you help me ?

You seem to be using Postgres (as suggested by the use of casting operator ::). If so - and I follow you correctly - you can use distinct on:
select distinct on(t.name)
r.severity, t.name as task, r.host, to_timestamp(r.date::bigint)::date
from tasks t
inner join results r on r.task = t.id
where t.name like '%corp 0%' and r.severity >= 7 and r.qod > 70
order by t.name, to_timestamp(r.date::bigint)::date desc
This guarantees one row per task only; which row is picked is controlled by the order by clause, so the above gets the row with the greatest date (time portion left apart). If there are ties, it is undefined which row is returned. You might want to adapt the order by clause to your exact requirement, if it is different than what I understood.
On the other hand, if you want top ties, then use window functions:
select *
from (
select r.severity, t.name as task, r.host, to_timestamp(r.date::bigint)::date,
rank() over(partition by t.name order by to_timestamp(r.date::bigint)::date desc) rn
from tasks t
inner join results r on r.task = t.id
where t.name like '%corp 0%' and r.severity >= 7 and r.qod > 70
) t
where rn = 1

Related

LAG() function in sql 2008

I have looked at a few other questions regarding this problem, we are trying to get a stored procedure working that contains the LAG() function, but the machine we are now trying to install an instance on is SQL 2008 and we can't use it
SELECT se.SetID,SetName,ParentSetId,
qu.QuestionID,qu.QuestionText,qu.QuestionTypeID,qu.IsPublished,qu.IsFilter,
qu.IsRequired,qu.QueCode,qu.IsDisplayInTable,
Case when (LAG(se.ParentSetId) OVER(ORDER BY se.ParentSetId) <> ParentSetId) then 2 else 1 end level ,
QuestionType
FROM tblSet se
LEFT join tblQuestion qu on qu.SetID=se.SetID
Inner join tblQuestionType qt on qt.QuestionTypeID=qu.QuestionTypeID and qt.IsAnswer=1
where CollectionId=#colID and se.IsDeleted=0
order by se.SetID
What I've tried so far (edited to reflect Zohar Peled's) suggestoin
SELECT se.SetID,se.SetName,se.ParentSetId,
qu.QuestionID,qu.QuestionText,qu.QuestionTypeID,qu.IsPublished,qu.IsFilter,
qu.IsRequired,qu.QueCode,qu.IsDisplayInTable,
(case when row_number() over (partition by se.parentsetid
order by se.parentsetid
) = 1
then 1 else 2
end) as level,
QuestionType
FROM tblSet se
left join tblSet se2 on se.ParentSetId = se2.ParentSetId -1
LEFT join tblQuestion qu on qu.SetID=se.SetID
Inner join tblQuestionType qt on qt.QuestionTypeID=qu.QuestionTypeID and qt.IsAnswer=1
where se.CollectionId=#colID and se.IsDeleted=0
order by se.SetID
it does not seem to be bringing out all of the same records when I run them side by side and the level value seems to be different also
I have put in some of the outputs into a HTML formatted table from the version containing LAG() (the first results) then the second is the new version, where the levels are not coming out the same
https://jsfiddle.net/gyn8Lv3u/
LAG() can be implemented using a self-join as Jeroen wrote in his comment, or by using a correlated subquery. In this case, it's a simple lag() so the correlated subquery is also simple:
SELECT se.SetID,SetName,ParentSetId,
qu.QuestionID,qu.QuestionText,qu.QuestionTypeID,qu.IsPublished,qu.IsFilter,
qu.IsRequired,qu.QueCode,qu.IsDisplayInTable,
Case when (
(
SELECT TOP 1 ParentSetId
FROM tblSet seInner
WHERE seInner.ParentSetId < se.ParentSetId
ORDER BY seInner.ParentSetId DESC
)
<> ParentSetId) then 2 else 1 end level ,
QuestionType
FROM tblSet se
LEFT join tblQuestion qu on qu.SetID=se.SetID
Inner join tblQuestionType qt on qt.QuestionTypeID=qu.QuestionTypeID and qt.IsAnswer=1
where CollectionId=#colID and se.IsDeleted=0
order by se.SetID
If you had specified an offset it would be harder do implement using a correlated subquery, and a self join would make a much easier solution.
Sample data and desired results would help. This construct:
(case when (LAG(se.ParentSetId) OVER(ORDER BY se.ParentSetId) <> ParentSetId) then 2 else 1
end) as level
is quite strange. You are lagging by the only column used in the order by. That makes sense. But then you are comparing the value to the same column, implying that there are duplicates.
If you have duplicates, then order by se.ParentSetId is unstable. That is, the "previous" row is indeterminate because of the duplicate values being ordered. You can run the query twice and get different results.
I am guessing you want one row with the value 1 for each parent set id. If so, then in either database, you would use:
(case when row_number() over (partition by se.parentsetid
order by se.parentsetid
) = 1
then 1 else 2
end) as level
This also has the problem with an unstable ordering. You can fix this by changing the order by to what you really want.

Multiple results - Need only the latest price

I need to find the latest price for some items
This is my query:
SELECT
MAX("POPORH1"."DATE") as "PO DATE",
"ICSHEH"."DOCNUM",
"ICSHEH"."TRANSDATE",
"ICSHEH"."FISCYEAR",
"ICSHEH"."FISCPERIOD",
"ICSHEH"."REFERENCE",
"ICSHED"."ITEMNO",
"ICSHED"."ITEMDESC",
"ICSHED"."LOCATION",
"ICSHED"."QUANTITY",
"ICSHED"."UNIT",
"POPORL"."UNITCOST"
FROM (("CABDAT"."dbo"."ICSHEH" "ICSHEH"
INNER JOIN
"CABDAT"."dbo"."ICSHED" "ICSHED" ON "ICSHEH"."SEQUENCENO"="ICSHED"."SEQUENCENO")
INNER JOIN "CABDAT"."dbo"."POPORL" "POPORL" ON "ICSHED"."ITEMNO"="POPORL"."ITEMNO")
INNER JOIN "CABDAT"."dbo"."POPORH1" "POPORH1" ON "POPORL"."PORHSEQ"="POPORH1"."PORHSEQ"
WHERE "ICSHED"."SEQUENCENO"=55873
group by
"ICSHEH"."DOCNUM",
"ICSHEH"."TRANSDATE",
"ICSHEH"."FISCYEAR",
"ICSHEH"."FISCPERIOD",
"ICSHEH"."REFERENCE",
"ICSHED"."ITEMNO",
"ICSHED"."ITEMDESC",
"ICSHED"."LOCATION",
"ICSHED"."QUANTITY",
"ICSHED"."UNIT",
"POPORL"."UNITCOST"
This query returns multiple results
These are the results:
"PODATE"='20180405' "ITEMNO"='2944' "UNITCOST"='0.266750'
"PODATE"='20180405' "ITEMNO"='2946' "UNITCOST"='0.266750'
"PODATE"='20170208' "ITEMNO"='2944' "UNITCOST"='0.250780'
"PODATE"='20170208' "ITEMNO"='2944' "UNITCOST"='0.250780'
"PODATE"='20170208' "ITEMNO"='2946' "UNITCOST"='0.250780'
"PODATE"='20170208' "ITEMNO"='2946' "UNITCOST"='0.250780'
I need to have only
"PODATE"='20180405' "ITEMNO"='2944' "UNITCOST"='0.266750'
"PODATE"='20180405' "ITEMNO"='2946' "UNITCOST"='0.266750'
I am learning SQL, so please be patient with my ignorance...
Thanks a lot!
You just need row_number().
WITH cte as (
SELECT *, ROW_NUMBER() OVER (PARTITION BY "ITEMNO" ORDER BY "PODATE" DESC) as rn
FROM "ICSHED" -- or join tables
WHERE "ICSHED"."SEQUENCENO"=55873
)
SELECT *
FROM cte where rn = 1
Or if you only need the highest value without any grouping can use TOP 1
SELECT TOP 1 *
FROM "ICSHED" -- or join tables
WHERE "ICSHED"."SEQUENCENO"=55873
ORDER "PODATE" DESC
By my understanding, you want top 2 rows with recent date. so I try this,
select top 2 * from yourtable order by dateCol desc

SQL Subquery just return one value.How Can make this code efficient?

select count(*) as CountId, [FirstRouteNo],[ThroughRouteSid],[LastRouteNo],
(select top 1 [ThroughRouteJson]
from DirectTransfer as Subquery
where MainQuery.FirstRouteNo=Subquery.FirstRouteNo and
MainQuery.ThroughRouteSid = Subquery.ThroughRouteSid and
MainQuery.LastRouteNo = Subquery.LastRouteNo
) as DetailJson,
(select top 1 RouteMeter
from DirectTransfer as Subquery
where MainQuery.FirstRouteNo = Subquery.FirstRouteNo and
MainQuery.ThroughRouteSid = Subquery.ThroughRouteSid and
MainQuery.LastRouteNo = Subquery.LastRouteNo
) as RouteMeter
from DirectTransfer as MainQuery
group by MainQuery.[FirstRouteNo],MainQuery.[ThroughRouteSid],MainQuery.[LastRouteNo]
order by CountId desc
I want to group by this column [FirstRouteNo],[ThroughRouteSid],[LastRouteNo] then Count How many records.but I also want to show two column values like [ThroughRouteJson] and [RouteMeter] any one of records.Because [ThroughRouteJson] and [RouteMeter] of value has little different.So I can't group by with them.then subquery only return one value.So I write two Subquery to get what I want.because my DB table has More than 100 million records.I want to make efficient. How can I make this code become more efficient then I can get the same result data?
I would suggest you do this as:
select dt.*, dt2.DetailJson, dt2.RouteMeter
from (select count(*) as cnt, dt.FirstRouteNo, dt.ThroughRouteSid, dt.LastRouteNo
from DirectTransfer dt
group by dt.FirstRouteNo, dt.ThroughRouteSid, dt.LastRouteNo
) dt outer apply
(select top 1 ThroughRouteJson as DetailJson, RouteMeter
from DirectTransfer dt2
where dt.FirstRouteNo = dt.FirstRouteNo and
dt.ThroughRouteSid = dt.ThroughRouteSid and
dt.LastRouteNo = dt.LastRouteNo
) dt2
order by CountId desc;
You want indexes on DirectTransfer(FirstRouteNo, ThroughRouteSid, LastRouteNo). There might be other ways to accomplish what you want, but it is a bit unclear what you are trying to do.

Find records in SQL Server 2008 R2

Please find below image for make understanding my issues. I have a table as shown below picture. I need to get only highlighted (yellow) records. What is the best method to find these records?
In SQL Server 2012+, you can use the lead() and lag() functions. However, this is not available in SQL Server 2008. Here is a method using outer apply:
select t.*
from t outer apply
(select top 1 tprev.*
from t tprev
on tprev.time < t.time
order by tprev.time desc
) tprev outer apply
(select top 1 tnext.*
from t tnext
on tnext.time > t.time
order by tnext.time asc
)
where (t.cardtype = 1 and tnext.cardtype = 2) or
(t.cardtype = 2 and tprev.cardtype = 1);
With your sample data, it would also be possible to use self joins on the id column. This seems unsafe, though, because there could be gaps in that columns values.
Havent tried this, but I think it should work. First, make a view of the table in your question, with the rownumber included as one column:
CREATE VIEW v AS
SELECT
ROW_NUMBER() OVER(ORDER BY id) AS rownum,
id,
time,
card,
card_type
FROM table
Then, you can get all the rows of type 1 followed by a row of type 2 like this:
SELECT
a.id,
-- And so on...
FROM v AS a
JOIN v AS b ON b.rownum = a.rownum + 1
WHERE a.card_type = 1 AND b.card_type = 2
And all the rows of type 2 preceded by a row of type 1 like this:
SELECT
b.id,
-- And so on...
FROM v AS b
JOIN v AS a ON b.rownum = a.rownum + 1
WHERE a.card_type = 1 AND b.card_type = 2
To get them both in the same set of results, you can just use UNION ALL. Technically, you don't need the view. You could use nested selects instead, but since you will need to query the table four times it might be nice to have it as a view.
Also, if the ID is continous (it goes 1, 2, 3 without any gaps), you don't need the rownum and can just use the ID instead.
here is a code you can run in sql server
select * from Table_name where id in (1,2,6,7,195,160,164,165)

Optimization of multiple aggregate sorting in SQL

I have a postgres query written for the Spree Commerce store that sorts all of it's products in the following order: In stock (then first available), Backorder (then first available), Sold out (then first available).
In order to chain it with rails scopes I had to put it in the order by clause as opposed to anywhere else. The query itself works, and is fairly performant, but complex. I was curious if anyone with a bit more knowledge could discuss a better way to do it? I'm interested in performance, but also different ways to approach the problem.
ORDER BY (
SELECT
CASE
WHEN tt.count_on_hand > 0
THEN 2
WHEN zz.backorderable = true
THEN 1
ELSE 0
END
FROM (
SELECT
row_number() OVER (dpartition),
z.id,
bool_or(backorderable) OVER (dpartition) as backorderable
FROM (
SELECT DISTINCT ON (spree_variants.id) spree_products.id, spree_stock_items.backorderable as backorderable
FROM spree_products
JOIN "spree_variants" ON "spree_variants"."product_id" = "spree_products"."id" AND "spree_variants"."deleted_at" IS NULL
JOIN "spree_stock_items" ON "spree_stock_items"."variant_id" = "spree_variants"."id" AND "spree_stock_items"."deleted_at" IS NULL
JOIN "spree_stock_locations" ON spree_stock_locations.id=spree_stock_items.stock_location_id
WHERE spree_stock_locations.active = true
) z window dpartition as (PARTITION by id)
) zz
JOIN (
SELECT
row_number() OVER (dpartition),
t.id,
sum(count_on_hand) OVER (dpartition) as count_on_hand
FROM (
SELECT DISTINCT ON (spree_variants.id) spree_products.id, spree_stock_items.count_on_hand as count_on_hand
FROM spree_products
JOIN "spree_variants" ON "spree_variants"."product_id" = "spree_products"."id" AND "spree_variants"."deleted_at" IS NULL
JOIN "spree_stock_items" ON "spree_stock_items"."variant_id" = "spree_variants"."id" AND "spree_stock_items"."deleted_at" IS NULL
) t window dpartition as (PARTITION by id)
) tt ON tt.row_number = 1 AND tt.id = spree_products.id
WHERE zz.row_number = 1 AND zz.id=spree_products.id
) DESC, available_on DESC
The FROM shown above determines whether or not a product is backorderable, and the JOIN shown above determines the stock in inventory. Note that these are very similar queries, except that I need to determine if something is backorderable based on a locations ability to support backorders and its state, WHERE spree_stock_locations.active=true.
Thanks for any advice!