SPROC T-SQL Syntax to return results if rows exist on multiple days - tsql

what I need to test for on my table is if there are rows for a given user id and order id on two separate days (DATETIME field for a timestamp).
I'm pretty sure I'd need a having clause and that's why I'm here...that frightens me terribly.

Having shouldn't scare you, it is just a "Where" on an aggregated field:
Select UserID, Count(*) From OrderTbl Group By UserID Having Count(*) > 1
That'll give you all the Users that have multiple orders.
Select UserID, Count(*) From OrderTbl Where (UserID=#UserID) Group By UserID Having Count(*) > 1
will give you the count if there are multiple records for the user id in #UserID and null if not.
if exists (Select UserID, Count(*) From OrderTbl Where (UserID=#UserID) Group By UserID
Having Count(*) > 1) Select 1 else Select 0
will return a 1 if there are multiple records for the User, 0 if not.
Update: Didn't realize that you could have multiple orders per day. This query will do what you want:
With DistinctDates as (Select Distinct UserID, [DATE] From OrderTbl Where (UserID=#UserID))
Select UserID, Count(*) From DistinctDates
Group By UserID Having Count(*) > 1

I am not sure if I understood your question, but this may work for you. The HAVING is your friend and you can still use the WHERE clause. This should let you know what order and user id combo is occuring more than once in the table.
SELECT [UserId], [OrderId]
FROM OrderTable
WHERE UserId = #UserId
AND OrderId = #OrderId
GROUP BY UserId, OrderId
HAVING Count(*) > 1

Related

Query to select by number of associated objects

I have two tables that look like the following:
Orders
------
id
tracking_number
ShippingLogs
------
tracking_number
created_at
stage
I would like to select the IDs of Orders that have ONLY ONE ShippingLog associated with it, and the stage of the ShippingLog must be error. If it has two ShippingLog entries, I don't want it. If it has one ShippingLog bug its stage is shipped, I don't want it.
This is what I have, and it doesn't work, and I know why (it finds the log with the error, but has no way of knowing if there are others). I just don't really know how to get it the way I need it.
SELECT DISTINCT
orders.id, shipping_logs.created_at, COUNT(shipping_logs.*)
FROM
orders
JOIN
shipping_logs ON orders.tracking_number = shipping_logs.tracking_number
WHERE
shipping_logs.created_at BETWEEN '2021-01-01 23:40:00'::timestamp AND '2021-01-26 23:40:00'::timestamp AND shipping_logs.stage = 'error'
GROUP BY
orders.id, shipping_logs.created_at
HAVING
COUNT(shipping_logs.*) = 1
ORDER BY
orders.id, shipping_logs.created_at DESC;
If you want to retain every column from the join of the two tables given your requirements, then I would suggest using COUNT here as an analytic function:
WITH cte AS (
SELECT o.id, sl.created_at,
COUNT(*) OVER (PARTITION BY o.id) num_logs,
COUNT(*) FILTER (WHERE sl.stage <> 'error')
OVER (PARTITION BY o.id) non_error_cnt
FROM orders o
INNER JOIN shipping_logs sl ON sl.tracking_number = o.tracking_number
WHERE sl.created_at BETWEEN '2021-01-01 23:40:00'::timestamp AND
'2021-01-26 23:40:00'::timestamp
)
SELECT id AS order_id, created_at
FROM cte
WHERE num_logs = 1 AND non_error_cnt = 0
ORDER BY id, created_at DESC;

select row number for given record id with postgres row_number() function

Sry, if my question isn't new but i can't find answer. I want to find row number for given id in postgres table.I have the folowing Postgres query
"SELECT row_number() over (ORDER BY id DESC) FROM
(SELECT id, row_number() over () FROM user ORDER BY id DESC) AS sub
WHERE id = ?1"
?1 - user id
This query always return 1 for any user id, but i need that it return actual record row number. For example, if i have 50 records in my database with ids from 1 to 50 and i execute query with id = 30, i want to retun row_number = 30. Thanks in advance.
If I followed you correctly, you could just use an aggregate query:
select count(*) rn
from user
where id <= ?1
This counts how many records have an id that is smaller (or equal) to the given parameter.

postgres select count distinct returning unexpected extra row

If there is one more UID in sessions than there is in users (obviously not supposed to be that way), then I expect to have a non-empty result set when I run the last select, but I get no rows returned - this result just doesn't make logical sense to me...
select count(distinct(uid)) from users;
> 108736
select count(distinct(uid)) from sessions;
> 108737
select count(*) from sessions where uid not in (select uid from users);
> 0
and just for completeness:
select count(*) from users where uid not in (select uid from sessions);
> 0
I have checked for nulls:
select count( * ) from sessions where uid is null;
> 0
select count( * ) from users where uid is null;
> 14
The schema is defined in sqlalchemy and includes a foreign key in the session table:
uid = Column(Integer, ForeignKey('users.uid', use_alter=True, name='fk_uid'))
This schema is a static dump for analytics purposes so there is no chance of concurrency issues...
Your third query does not do what you think it does.
The following query illustrates the problem:
SELECT 1 NOT IN (SELECT unnest(ARRAY[NULL]::int[]));
This returns NULL, because it can't say if 1 <> NULL.
So, in your query the where condition is always NULL, because users contains a NULL uid.
I recommend using EXCEPT do find the culprit in your sessions table.
SELECT uid from sessions EXCEPT SELECT uid from users;

Getting value from table with max key

I have a table with two columns:
UserId (auto int)
Email(Nvarchar)
I want to retrieve the email that was last inserted on table.
I've tried some options, but nothing seems to be working.
Thanks in advance.
Perhaps simply:
SELECT TOP 1 email FROM dbo.Table ORDER BY UserId DESC
or
SELECT UserId, Email
FROM dbo.Table
WHERE UserId = (SELECT MAX(UserId) FROM dbo.Table)
However, it's not good practise to abuse a primary-key column for information like "last inserted". Add a datetime column for this.
You could also use the ROW_NUMBER function:
WITH x AS (
SELECT UserId, Email,
rn = Row_number() OVER(ORDER BY UserId DESC)
FROM dbo.table)
SELECT UserId, Email
FROM x
WHERE rn = 1

Tsql, returning rows with identical column values

Given an example table 'Users', which has an int column named 'UserID' (and some arbitrary number of other columns), what is the best way to select all rows from which UserID appears more than once?
So far I've come up with
select * from Users where UserID in
(select UserID from Users group by UserID having COUNT(UserID) > 1)
This seems like quite an innefficient way to do this though, is there a better way?
In SQL Server 2005+ you could use this approach:
;WITH UsersNumbered AS (
SELECT
UserID,
rownum = ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY UserID)
FROM Users
)
SELECT u.*
FROM Users u
INNER JOIN UsersNumbered n ON u.UserID = n.UserID AND n.rownum = 2
Provided there exists a non-clustered index on UserID, this yields a slightly worse execution plan than your approach. To make it better (actually, same as yours), you'll need to use... a subquery, however counter-intuitive it may seem:
;WITH UsersNumbered AS (
SELECT
UserID,
rownum = ROW_NUMBER() OVER (PARTITION BY UserID ORDER BY UserID)
FROM Users
)
SELECT u.*
FROM Users u
WHERE EXISTS (
SELECT *
FROM UsersNumbered n
WHERE u.UserID = n.UserID AND n.rownum = 2
);
In case of a clustered index on UserID all three solutions give the same plan.
This would do the same thing but evaluate the performance and it would likely be faster/more efficient. Of course there should be an index on this UserID column.
select u.*
from Users u
join (select UserID,count(UserID) as CUserID from Users group by UserID) u1 on u1.UserID = u.UserID
where CUserID > 1