How to get the rows that are an error with their latest sequence? - sql

The objective is to get the rows that are an error with their latest sequence. sample data as follows, Temptable is used since it useful for further transactions
here is my query
SELECT MAX(cc.[sequence]) [sequence],
OrderID,
OrderItemID
INTO #tmpErrorRecords
FROM [TMC].CVOrderCompletions cc
WHERE cc.[status] = 0
AND LTRIM(RTRIM(ISNULL(errorMessage, ''))) <> ''
GROUP BY cc.OrderID,
cc.OrderItemID;
My lead reviews the above query and says, There is still going to be a bug in the way you are selecting the error rows in the temp table. I have revised the code that selects the error rows and it should look like below.
But I'm wondering what is the difference between the above and the revised query? Appreciate if somebody could help me with this please
SELECT MAX(cc.[sequence]) [sequence],
OrderID,
OrderItemID
INTO #tmpOCRecords
FROM TMC.CVOrderCompletions cc
GROUP BY cc.OrderID,
cc.OrderItemID;
SELECT cc.[sequence],
cc.OrderID,
cc.OrderItemID
INTO #tmpErrorRecords
FROM TMC.CVOrderCompletions cc
INNER JOIN #tmpOCRecords tc ON(cc.OrderID = tc.OrderID
AND cc.OrderItemID = tc.OrderItemID
AND cc.[sequence] = tc.[sequence]
AND LTRIM(RTRIM(ISNULL(cc.errorMessage, ''))) != ''
AND cc.STATUS = 0);

What your lead could/should have told you is that cc.[status] = 0 is not going to fetch any rows for the shown sample data...
What defines an error row? It has an error message.
This is the only filter you need. Do not overcomplicate things.
Sample data
(Text data that can be copy-pasted instead of images next time, please!)
create table tmpErrors
(
id int,
orderId int,
orderItemId int,
sequence int,
status int,
errorMessage nvarchar(100)
);
insert into tmpErrors (id, orderId, OrderItemId, sequence, status, errorMessage) values
( 1, 1136832, 1, 0, 1, null),
( 2, 1136832, 1, 1, 1, null),
( 3, 1142898, 1, 0, 1, 'Sql procedure ...'),
( 4, 1142898, 1, 1, 1, 'Sql procedure ...'),
( 5, 1142898, 1, 2, 1, 'Sql procedure ...'),
( 6, 1142898, 1, 3, 1, 'Sql procedure ...'),
( 7, 1142904, 1, 0, 1, null),
( 8, 1142910, 1, 0, 1, 'Invoice record ...'),
( 9, 1142910, 1, 1, 1, 'Invoice record ...'),
(10, 1142910, 1, 2, 1, 'Invoice record ...'),
(11, 1142916, 1, 0, 1, null);
Solution
select te.orderId,
te.orderItemId,
max(te.sequence) as sequence
from tmpErrors te
where te.errorMessage is not null
group by te.orderId,
te.orderItemId;
Result
orderId orderItemId sequence
------- ----------- --------
1142898 1 3
1142910 1 2
Fiddle to see things in action.

Related

Having Trouble Summing distinct values

I have a fairly poorly designed DB that I'm trying to pull reports from. I'm attempting to sum the value on the column GuestCount, however with the structure of the joins, i'm getting a cartesian situation that's making the sum inaccurate. I can't use Sum(Distinct) because I'm not trying to sum the distinct values in GuestCount, but rather the sum of distinct rows.
Here's the SQL to set up the Tables:
CREATE TABLE TesttblTransactions (
ID int,
[sysdate] date,
TxnHour tinyint,
Facility nvarchar(50),
TableID int,
[Check] int,
Item int,
Parent int
)
Create Table TesttblTablesGuests (
ID int,
Facility nvarchar(50),
TableID int,
GuestCount tinyint,
TableDate Date
)
Create Table TesttblFacilities (
ID int,
ClientKey nvarchar(50),
Brand nvarchar(50),
OrgFacilityID nvarchar(50),
UnitID smallint
)
INSERT INTO testtbltransactions (
ID,
[Sysdate],
TxnHour,
Facility,
TableID,
[Check],
Item,
Parent
)
VALUES
(
1,
'20221201',
7,
'JOES',
1001,
12345,
8898989,
0
),
(
2,
'20221201',
7,
'JOES',
1001,
12345,
8776767,
1
),
(
3,
'20221201',
7,
'JOES',
1001,
12345,
856643,
0
),
(
4,
'20221201',
7,
'THE DIVE',
1001,
67890,
662342,
0
),
(
5,
'20221201',
7,
'THE DIVE',
1001,
67890,
244234,
0
),
(
6,
'20221201',
7,
'JOES',
1002,
12344,
873323,
0
);
INSERT INTO testtblTablesGuests (
ID,
Facility,
TableID,
GuestCount,
TableDate
)
VALUES
(
1,
'JOES',
1001,
4,
'20221201'
),
(
2,
'THE DIVE',
1001,
1,
'20221201'
),
(
3,
'JOES',
1002,
1,
'20221201'
);
INSERT INTO testtblFacilities (
ID,
ClientKey,
Brand,
OrgFacilityID,
UnitID
)
VALUES
(
1,
'JOES',
'Joes Hospitality Group LLC',
'Joes Bar',
987
),
(
2,
'THE DIVE',
'The Dive Restaurant Group',
'The Dive',
565
);
--Here's the SQL that I need for reporting but can't seem to get working:
Declare #StartDate as Date = '12-1-2022'
Declare #EndDate as Date = '12-1-2022'
--The query we want to work
SELECT
TesttblFacilities.ClientKey,
TesttblFacilities.Brand,
format(testtbltransactions.sysdate,'yyyy-MM-dd') AS [Date],
'H' AS Freqency,
Testtbltransactions.[TxnHour] AS [Hour],
TesttblFacilities.UnitID AS [UnitID],
'Dine In Guest Count' as Metric,
Sum(TesttblTablesGuests.GuestCount) AS [Value]
FROM ((Testtbltransactions
JOIN Testtbltablesguests ON (Testtbltablesguests.TableDate = Testtbltransactions.sysdate) AND (Testtbltransactions.FACILITY = Testtbltablesguests.facility) AND (Testtbltransactions.tableid = Testtbltablesguests.tableid))
JOIN TesttblFacilities ON Testtbltransactions.FACILITY = TesttblFacilities.ClientKey)
Where (((Testtbltransactions.parent)=0))
and Testtbltransactions.sysdate >= #StartDate
and Testtbltransactions.sysdate <= #EndDate
GROUP BY TesttblFacilities.ClientKey, Testtblfacilities.UnitID,TesttblFacilities.Brand, Testtbltransactions.facility, Testtbltransactions.sysdate, Testtbltransactions.TxnHour`
I'm getting 9 and 2, instead of 5 and 1.
In the comments NBK suggested doing a subquery - and it took me a while but I think i found something that works.. . .
Declare #StartDate as Date = '12-1-2022'
Declare #EndDate as Date = '12-1-2022'
Select
t1.txnhour,
t1.facility,
SUM(t1.guestcount) from
(
Select Distinct
TesttblTransactions.TableID as TableID,
testtbltransactions.[txnHour] as txnhour,
testtbltransactions.Facility as Facility,
testtbltablesguests.GuestCount as guestcount,
testtbltransactions.Parent as parent
From TesttblTransactions
Join TesttblTablesGuests on TesttblTablesGuests.TableID = TesttblTransactions.TableID and testtbltablesguests.Facility = TesttblTransactions.Facility
Where (((Testtbltransactions.parent)=0))
and Testtbltransactions.sysdate >= #StartDate
and Testtbltransactions.sysdate <= #EndDate
) T1
Group by t1.Facility, t1.txnhour, t1.Facility
I'm going to continue to refine this, but I think I should be able to move forward with this.

How can I set order counting in insert statement SQL Server?

I tried to copy data from database to another database
I have this query
insert into d1.dbo.Category(Id, Name, CategoryTemplateId,
ParentCategoryId, PictureId, PageSize,
AllowCustomersToSelectPageSize,
ShowOnHomePage, IncludeInTopMenu,
SubjectToAcl, LimitedToStores, Published,
Deleted, DisplayOrder,
CreatedOnUtc, UpdatedOnUtc)
select
(ItemID + 25), ItemName, 1,
(CategoryID + 16), '', 6,
1, 1, 1, 0, 0, 1, 0, 1,
iif(CreateDate is null, GETDATE(), CreateDate),
iif(LastModifyDate is null, GETDATE(), LastModifyDate)
from
d2.dbo.Item
It works fine. The question is: there is a column DisplayOrder if I use this syntax it will insert 1 in al the rows, but what I really need is to count 1,2,3,4,.. etc
Depends on (CategoryID + 16) until (CategoryID + 16) changed it start count from 1 again
Please help
Use row_number() over (partition by CategoryId order by (select null)) to populate an increasing value in DisplayOrder. (Note: The + 16 is redundant in the partition by.)
Also, instead of this construct:
iif(CreateDate is null,GETDATE(),CreateDate)
Use the simpler, more standard syntax:
coalesce(CreateDate, GETDATE())

Query for Multiple records showing as a single line

I have a Table, Table Contains lot of records with lot of Applicant Unique Number,
SINo , ApplUniqNo, Amount, PaymentId,Year
1, 203, 2583.02, 1, 2014-15
2, 307, 1254.25, 2, 2014-15
3, 203, 2413.50, 2, 2014-15
4, 203, 5689.32, 1, 2014-15
The Above table showing same records ApplUniqNo:203,
My Requirment is display like this
ApplUniqNo,Amount,PaymentId
203, 2583.02/2413.50/5689.32 ,1/2/1
Could you please Help me. write a Query for Procedure.
You can use FOR XML for this
;WITH CTE AS
(
SELECT
ApplUniqNo
,(SELECT
CONVERT(VARCHAR,Amount)+'/' from #TempTable Amounts WHERE Amounts.ApplUniqNo = YourTable.ApplUniqNo
FOR XML PATH('') ) AS Amount
,(SELECT
CONVERT(VARCHAR,PaymentId)+'/' from #TempTable PaymentIds WHERE PaymentIds.ApplUniqNo = YourTable.ApplUniqNo
FOR XML PATH('')) AS PaymentID
FROM
YourTable
)
SELECT
ApplUniqNo
,SUBSTRING(Amount,0,LEN(Amount)) AS Amount
,SUBSTRING(PaymentID,0,LEN(PaymentID)) AS PaymentID
FROM
CTE
The common table expression is used to remove the last extra '/' using substring

Sql: Select where a condition is true for all types

I have a table defined and populated as follows:
DECLARE #Temp TABLE
(
ProjectId INT,
EmployeeId INT,
SomeTypeId INT,
IsExpired BIT,
IsWarning BIT,
IsIncomplete BIT
)
--all incomplete...
INSERT INTO #Temp VALUES (1, 1, 1, 0, 0, 1)
INSERT INTO #Temp VALUES (1, 1, 2, 0, 0, 1)
INSERT INTO #Temp VALUES (1, 1, 3, 0, 0, 1)
--two warnings...
INSERT INTO #Temp VALUES (1, 2, 1, 0, 1, 0)
INSERT INTO #Temp VALUES (1, 2, 2, 0, 1, 0)
INSERT INTO #Temp VALUES (1, 2, 3, 0, 0, 0)
--two expirations...
INSERT INTO #Temp VALUES (1, 3, 1, 0, 0, 0)
INSERT INTO #Temp VALUES (1, 3, 2, 1, 0, 0)
INSERT INTO #Temp VALUES (1, 3, 3, 1, 0, 0)
I want to return distinct ProjectId, EmployeeId pairs with any warnings or expirations:
SELECT DISTINCT ProjectId, EmployeeId FROM #Temp WHERE IsWarning = 1 OR IsExpired = 1
No problem.
However, I'd like to also return ProjectId, EmployeeId pairs where IsWarning = 0 and IsExpired = 0 and IsIncomplete = 1, but this must be true for all SomeTypeId's (1, 2, 3). In other words, no warnings, no expirations, just incomplete for all categories.
SomeTypeId Fks to a lookup table. Right now there are only 3 entries, but there could be more in the future.
Any ideas?
I would expect ProjectId, EmployeeId (1, 1) to be returned.
This uses MAX and MIN to see to that all values are the same; one needs to add a + 0 to each bit to make it available to normal numeric aggregate functions (like MIN/MAX/SUM/...)
SELECT ProjectId, EmployeeId
FROM Temp
GROUP BY ProjectId, EmployeeId
HAVING MAX(IsWarning + 0) = 0
AND MAX(IsExpired + 0) = 0
AND MIN(IsIncomplete + 0) = 1
An SQLfiddle for testing.
I'm not sure from your question if you mean that you want those results in the SAME query, or you want an entirely new query. Assuming the latter, your query would be:
SELECT DISTINCT ProjectId, EmployeeId FROM #Temp WHERE (IsWarning = 0 AND IsExpired = 0 AND IsIncomplete = 1)
Assuming the former, it would be:
SELECT DISTINCT ProjectId, EmployeeId FROM #Temp WHERE (IsWarning = 1 OR IsExpired = 1)
OR (IsWarning = 0 AND IsExpired = 0 AND IsIncomplete = 1)
Try this assuming you have no duplicate records;
Please note that union is added assuming you still need to select data WHERE IsWarning = 1 OR IsExpired = 1. If you don't need them simply remove it.
SQL-DEMO HERE
;with cte as (
select projectid, employeeid,
case when sometypeid in (1,2,3) and
IsWarning = 0 and IsExpired = 0 and IsIncomplete = 1
then 1 else 0 end x
from temp
)
select projectid, employeeid
from cte
group by projectId, employeeid
having sum(x) >= 3
union
select projectid, employeeid
from Temp
where IsWarning = 1 or IsExpired = 1

Need help writing SQL to retrieve list based on complex rules

It seems like this title has been used many times before, unfortunately I don't know how else to describe my problem. So, first off, if you have a suggestion for a better title that will help future searchers, fire away!
Anyway, my problem is trying to write the SQL to return a resultset based on a set of rules applied to the following schema:
TABLE: Tests
COLUMNS: ID (PK), Name
TABLE: TestVersions
COLUMNS: TestID (PK), Version (PK), IsActive
TABLE: TestSessions
COLUMNS: TestID (PK), TestVersion (PK), UserID (PK), Iteration (PK), Completed, CompletionDate
There is a relationship between [Tests] and [TestVersions] on [Tests].[ID] = [TestVersions].[TestID]. There is also a relationship between [TestSessions] and [TestVersions] on [TestSessions].[TestID] = [TestVersions].[TestID] AND [TestSessions].[TestVersion] = [TestVersions].[Version]
The result set should return [Tests].[ID], [Tests].[Name] and [TestVersions].[Version] based on the following rules:
Any Test that has an associated record in TestSessions where Complete is false.
The maximum Version for any Test that has no associated records in TestSessions but IsActive is true.
This one is the complicated one. If a Test has associated records in TestSessions where all are completed (Complete is true) and has at least one associated record in TestVersions with IsActive true, I need to verify that the most recent CompletionDate is at least 30 days ago and, if so, return the highest Version from TestVersions.
Hopefully this makes sense.
Here's a quick script that creates temp tables, fills them with data, and shows you how i'd approach the problem you're having. Let me say up front that this kind of stuff is sometimes best left to the business logic layers. Also, I'm not sure that your description is very accurate because there seem to be some inconsistencies. With that said, I hope you can take away how to approach your problem, break it down into parts and solve it. Don't worry about optimizing up front, just write clean and logical code. Optimizer will tell you if you're making any mistakes. This assumes SQL Server 2008:
declare #Tests table
(
ID int,
Name varchar(100)
)
declare #TestVersions table
(
TestID int,
Version int,
IsActive bit
)
declare #TestSessions table
(
TestID int,
TestVersion int,
UserID varchar(100),
Iteration int,
Completed bit,
CompletionDate date
)
insert into #Tests
select 1, 'one' union all
select 2, 'two' union all
select 3, 'three' union all
select 4, 'four' union all
select 5, 'five'
insert into #TestVersions
select 1, 1, 0 union all
select 2, 1, 1 union all
select 3, 1, 0 union all
select 4, 1, 0 union all
select 5, 1, 1 union all
select 1, 2, 0 union all
select 2, 2, 0 union all
select 3, 2, 1 union all
select 4, 2, 0 union all
select 1, 3, 1 union all
select 2, 3, 1
insert into #TestSessions
select 1, 1, 'a', 1, 1, GETDATE()-101 union all
select 2, 1, 'b', 1, 1, GETDATE()-11 union all
select 3, 1, 'c', 1, 0, null union all
select 4, 1, 'd', 1, 1, GETDATE()-103 union all
select 5, 1, 'e', 1, 1, GETDATE()-101 union all
select 1, 2, 'f', 1, 1, GETDATE()-15 union all
select 2, 2, 'g', 1, 0, null union all
select 3, 2, 'h', 1, 1, GETDATE()-17 union all
select 4, 2, 'i', 1, 0, null union all
select 1, 3, 'j', 2, 1, GETDATE()-109 union all
select 2, 3, 'k', 2, 1, GETDATE()-101 union all
select 2, 1, 'l', 3, 1, GETDATE()-120 union all
select 3, 1, 'm', 1, 1, GETDATE()-11 union all
select 4, 1, 'n', 1, 1, GETDATE()-140 union all
select 5, 1, 'a', 1, 0, null union all
select 1, 2, 'b', 1, 1, GETDATE()-160 union all
select 2, 2, 'c', 2, 0, null union all
select 3, 2, 'd', 1, 1, GETDATE()-17 union all
select 4, 2, 'e', 1, 0, null union all
select 1, 3, 'f', 2, 1, GETDATE()-4 union all
select 2, 3, 'g', 3, 1, GETDATE()-101
select Id
,Name
,Version
from #Tests t
inner join
#TestVersions v on t.ID = v.TestID
-- any test with a session with completed = false
where exists
(select *
from #TestSessions s1
where s1.Completed = 0
and s1.TestID = t.ID
and s1.TestVersion = v.Version
)
or (
-- any max version of a test which has no sessions
not exists
(select *
from #TestSessions s1
where s1.TestID = t.ID
and s1.TestVersion = v.Version
)
and v.Version =
(select MAX(Version)
from #TestVersions v2
where v2.TestID = t.ID
)
)
or (
-- no uncompleted sessions
not exists
(select *
from #TestSessions s1
where s1.Completed = 0
and s1.TestID = t.ID
and s1.TestVersion = v.Version
)
-- we're already inner joining to versions, so we just need to check IsActive
and IsActive = 1
-- the most recent completion date is at least 30 days ago (not quite 30 days ago but i'm lazy)
and GETDATE() - 30 <=
(select MAX(CompletionDate)
from #TestSessions s2
where s2.TestID = t.ID
and s2.TestVersion = v.Version
)
-- not sure what you mean by "return", but I'm sure you can figure out how to project what you need
)
Here's what I ended up with (based on Milimetric's suggestion):
SELECT Tests.ID, Tests.Name, TestVersions.Version
FROM Tests INNER JOIN
TestVersions ON Tests.ID = TestVersions.TestID
WHERE (
EXISTS (SELECT *
FROM TestSessions
WHERE Complete = 0
AND TestID = Test.ID
AND TestVersion = TestVersions.Version)
)
OR
(
NOT EXISTS (SELECT *
FROM TestSessions
WHERE TestID = Tests.ID
AND TestVersion = TestVersions.Version)
AND (TestVersions.Version = (SELECT MAX(Version)
FROM TestVersions
WHERE TestID = Tests.ID))
AND TestVersions.IsActive = 1
AND TestVersions.StartDate <= GetDate()
AND (TestVersions.EndDate IS NULL OR TestVersions.EndDate >= GetDate())
)
OR
(
EXISTS (SELECT *
FROM TestSessions
WHERE Complete = 1
AND TestID = Tests.ID
AND TestVersion = TestVersions.Version)
AND (TestVersions.Version = (SELECT MAX(Version)
FROM TestVersions
WHERE TestID = Tests.ID))
AND (TestVersions.IsActive = 1)
AND (TestVersions.StartDate <= GetDate())
AND (TestVersions.EndDate IS NULL OR TestVersions.EndDate >= GetDate())
AND (GetDate() >= (SELECT DATEADD(day, 30, MAX(TestSessions.CompletionDate))
FROM TestSessions
WHERE TestSessions.TestID = Tests.ID
AND TestSessions.TestVersion = TestVersions.Version))