How to compute the number of sequence on an sentence in SQLite? - sql

I have one table which records the deliverings of some products to clients. Its basic scheme is very easy:
| DeliveryDate | IdClient | IdProduct | Quantity | Cost |
Well, one assumption is that the clients can only purchase one item at a time, and they begin purchasing Item1, eventually they could change and start buying Item2, stopping from buying Item1, and so on. That do not mean Item1, Item2, ..., ItemN is always the same product, they could vary.
So, what I want is being able to get the different items purchased for each costumer, with its initial date of purchase, and the number of sequence of each product for each client, since I could not guess in advance which item will be bought. With this scheme:
| IdClient | IdProduct | FirstTimeDate | NumSequence |
Let me explain with a sample:
Table:
| DeliveryDate | IdClient | IdProduct | Quantity | Cost |
| 2016-05-01 | 1234 | 9876 | 2 | 1000 |
| 2016-06-01 | 1234 | 9876 | 1 | 500 |
| 2016-07-01 | 1234 | 8765 | 2 | 2000 |
| 2016-08-01 | 1234 | 5432 | 3 | 3500 |
| 2016-06-01 | 3456 | 5432 | 2 | 1500 |
| 2016-07-01 | 3456 | 5432 | 1 | 700 |
| 2016-08-01 | 3456 | 9523 | 2 | 2500 |
Desired Output:
| IdClient | IdProduct | FirstTimeDate | NumSequence |
| 1234 | 9876 | 2016-05-01 | 1 |
| 1234 | 8765 | 2016-07-01 | 2 |
| 1234 | 5432 | 2016-08-01 | 3 |
| 3456 | 5432 | 2016-06-01 | 1 |
| 3456 | 9523 | 2016-08-01 | 2 |
I could manage to get everything, except the number of sequence, instead of that, with the sql sentence written below I can get the number of different products purchased for each client:
| IdClient | IdProduct | FirstTimeDate | NumOfDistinctProducts |
| 1234 | 9876 | 2016-05-01 | 3 |
| 1234 | 8765 | 2016-07-01 | 3 |
| 1234 | 5432 | 2016-08-01 | 3 |
| 3456 | 5432 | 2016-06-01 | 2 |
| 3456 | 9523 | 2016-08-01 | 2 |
And the sql (for simplicity, I run first one sql creating a temporary table, and after that I run the actual query):
// Query to create the temporary table:
CREATE TEMPORARY TABLE tmpNewDelivering AS WITH FT_CTE AS (
SELECT min(Date) ChangeDate,* FROM Deliverings WHERE Deliverings.IdProduct IN ( // Actual IdProducts // )
GROUP BY IdProduct, IdPatient
ORDER BY Deliverings.Date ASC
)
SELECT * from FT_CTE;
// Query I want to improve:
SELECT case when C.StartDate = tND.ChangeDate then "Start" else "Change" end Type, C.NumProducts NumProducts, tND.*
FROM tmpNewDelivering tND INNER JOIN (
SELECT IdClient, count(IdProduct) NumProducts, min(ChangeDate) StartDate
FROM tmpNewDelivering
GROUP BY IdClient
) C ON tND.IdClient = C.IdClient
ORDER BY tCN.Fecha DESC

SQLite does not have some capabilities that would be useful for this.
You an get the first three columns just using aggregation:
select IdClient, IdProduct, min(DeliveryDate) as FirstTimeDate
from IdClient
group by IdPatient, IdProduct;
To get the sequence, you can modify this to get the number of different products purchased on or before the current one:
| NumOfDistinctProducts
select IdClient, IdProduct, min(DeliveryDate) as FirstTimeDate,
(select count(distinct d2.IdProduct)
from Deliverings d2
where d2.IdClient = d.IdClient and
d2.DeliveryDate <= d.DeliveryDate
) as NumSequence
from Deliverings d
group by IdPatient, IdProduct;
Note: You can use a temporary table for this. If so, you can use the temporary table for the subquery. This is a good idea if you put an index on IdClient, DeliveryDate, IdProduct.

Related

Two foreign keys referring to one primary key on SQL SERVER query select items

I'd to create a database that records transactions between two users. A user can transfer points (think of it as money) to another user. user table looks like:
| userID | name | email | balance |
| ------------- |---------------|------------------|------------|
| 101 | alpha | alpha#mail.com | 1000 |
| 102 | bravo | bravo#mail.com | 500 |
| 103 | charlie | charlie#mail.com | 2000 |
And the transaction table should look like:
transactionID | from_user | to_user | transfer_amount |
| ------------- |---------------|------------------|------------------|
| 1 | 101 | 103 | 100 |
| 2 | 102 | 101 | 150 |
| 3 | 102 | 103 | 200 |
just i needed this result:
| row | from_user | to_user | transfer_amount |
| ------------- |---------------|------------------|------------------|
| 1 | alpha | charlie | 100 |
| 2 | bravo | alpha | 150 |
| 3 | bravo | charlie | 200 |
Could someone give hints to provide SQL Server code?
Select from_user, to_user, name, transfer_amount from transaction iner join users on trans.id==user.id;
SELECT T.TRANSACTION_ID,T.FROM_USER,U_FROM.NAME,
T.TO_USER,U_TO.NAME,T.TRANSFER_AMOUNT
FROM TRANSACTIONS AS T
JOIN USERS AS U_FROM ON T.FROM_USER=U_FROM.USER_ID
JOIN USERS AS U_TO ON T.TO_USER=U_TO.USER_ID
Something like this, I guess

SQL MAX query using 3 tables

I'm having difficulty querying an SQL database.
| patient_id | episode_number | attend_practitioner | pract_assignment_date |
| ---------- | -------------- | ------------------- | --------------------- |
| 111 | 4 | 4444 | 01/05/2017 |
| 222 | 8 | 5555 | 03/17/2017 |
| 222 | 8 | 6666 | 03/20/2017 |
| 222 | 9 | 7777 | 04/10/2017 |
| 333 | 2 | 5555 | 10/08/2017 |
| 444 | 7 | 7777 | 08/09/2017 |
| patient_id | episode_number | backup_practitioner | date_of_assignment |
| ---------- | -------------- | ------------------- | ------------------ |
| 111 | 4 | | |
| 222 | 8 | 7777 | 03/17/2017 |
| 222 | 8 | 4444 | 05/18/2017 |
| 222 | 9 | | |
| 333 | 2 | 4444 | 10/08/2017 |
| 333 | 2 | 5555 | 10/19/2017 |
| patient_id | episode_number | admit_date |
| ---------- | -------------- | ---------- |
| 111 | 4 | 01/05/2017 |
| 222 | 8 | 03/17/2017 |
| 222 | 9 | 03/20/2017 |
| 333 | 2 | 10/08/2017 |
I'm looking for an SQL query where I can enter a staff_id and then have it return all the open episodes they are currently assigned to. Result:
| staff_id | patient_id | episode_number | admit_date | date_of_assignment |
| -------- | ---------- | -------------- | ---------- | ------------------ |
| 4444 | 111 | 4 | 01/05/2017 | 01/05/2017 |
| 4444 | 222 | 8 | 03/17/2017 | 05/18/2017 |
I don't understand how the SQL handles aliases in the query.
The SQL doesn't know what to do with SQL window functions such as OVER, LAG(), LEAD(), etc. So I'm using self joins along with the MAX() function. Maybe this is an older SAP SQL server.
I don't know whether capitalization in the SQL query is irrelevant.
This is a bit hard to work out from your question. I thin you need to most recent assignment for each patient/episode.
You could do this with a second sub-query using max, or you could use not exists as per below.
As you mentioned, it would be much easier with a row_number() and or CTE's, but this is bulk standard sql version.
select s.staff_id, e.patient_id, e.episode_number as episode_id, e.admit_date, s.date_of_assignment, c.last_date_of_service
from episode_history e
join (
select patient_id, episode_number, attend_practitioner as staff_id, pract_assignment_date as date_of_assignment
from history_attending_practitioner
union
select patient_id, episode_number, backup_practitioner as staff_id, date_of_assignment as date_of_assignment
from user_practitioner_assignment
where backup_practitioner is not null
) s on s.patient_id=e.patient_id and s.episode_number=e.episode_number
and not exists(select * from history_attending_practitioner a2 where a2.patient_id=s.patient_id and a2.episode_number=s.episode_number and a2.pract_assignment_date>s.date_of_assignment)
and not exists(select * from user_practitioner_assignment a3 where a3.patient_id=s.patient_id and a3.episode_number=s.episode_number and a3.date_of_assignment>s.date_of_assignment)
join view_episode_summary_current c on c.patient_id=e.patient_id and c.episode_number=e.episode_number
where e.discharge_date is null
After tweaking the query items, this is the SQL query version that returned the correct results:
SELECT
t1.staff_id
, t1.patient_id
, t3.admit_date
, t1.episode_number
, t1.date_of_assignment
FROM
/* select the most recent attending practitioner entry from table1 for the patient and episode */
(SELECT attending_practitioner AS staff_id, patient_id, episode_number, pract_assignment_date AS date_of_assignment
FROM table1 AS t1a
WHERE t1a.pract_assignment_date =
(SELECT MAX(pract_assignment_date)
FROM table1 AS t1b
WHERE t1b.patient_id = t1a.patient_id
AND t1b.episode_number = t1a.episode_number)
UNION
/* select the most recent practitioner entry from table2 for the patient and episode */
SELECT backup_practitioner AS staff_id, patient_id, episode_number, date_of_assignment
FROM table2 AS t2a
WHERE t2a.date_of_assignment =
(SELECT MAX(date_of_assignment)
FROM table2 AS t2b
WHERE t2b.patient_id = t2a.patient_id
AND t2b.episode_number = t2a.episode_number)
) AS t1
INNER JOIN
/* filter out closed episodes by using the table3 */
(SELECT patient_id AS patient_id2, episode_number AS episode_number2, admit_date
FROM table3) AS t3
ON t3.patient_id = t1.patient_id
AND t3.episode_number2 = t1.episode_number
WHERE t1.staff_id = '4444'

Return Max Value Date for each group in Netezza SQL

+--------+---------+----------+------------+------------+
| CASEID | USER ID | TYPE | OPEN_DT | CLOSED_DT |
+--------+---------+----------+------------+------------+
| 1 | 1000 | MA | 2017-01-01 | 2017-01-07 |
| 2 | 1000 | MB | 2017-07-15 | 2017-07-22 |
| 3 | 1000 | MA | 2018-02-20 | NULL |
| 8 | 1001 | MB | 2017-05-18 | 2018-02-18 |
| 9 | 1001 | MA | 2018-03-05 | 2018-04-01 |
| 7 | 1002 | MA | 2018-06-01 | 2018-07-01 |
+--------+---------+----------+------------+------------+
This is a snippet of my data set. I need a query that returns just the max(OPEN_DT) row for each USER_ID in Netezza SQL.
so given the above the results would be:
| CASEID | USERID | TYPE | OPEN_DT | CLOSED_DT |
| 3 | 1000 | MA | 2018-02-20 | NULL |
| 9 | 1001 | MA | 2018-03-05 | 2018-04-01 |
| 7 | 1002 | MA | 2018-06-01 | 2018-07-01 |
Any help is very much appreciated!
You can use correlated subquery :
select t.*
from table t
where open_dt = (select max(t1.open_dt) from table t1 where t1.user_id = t.user_id);
You can also row_number() :
select t.*
from (select *, row_number() over (partition by user_id order by open_dt desc) as seq
from table t
) t
where seq = 1;
However if you have a ties with open_dt then you would need to use limit clause with correlated subquery but i am not sure about the ties so i just leave it.

Having Groups based on distinct count of another column

I have a table as follow :
+-------------+-----------+------+
| GroupNumber | TeamName | Goal |
+-------------+-----------+------+
| 1 | Sales | ABC |
| 1 | Sales | ABC |
| 1 | Sales | ABC |
| 1 | Design | XYZ |
| 2 | Design | XYZ |
| 2 | Sales | XYZ |
| 2 | technical | XYZ |
| 2 | Support | XYZ |
| 3 | Sales | XYZ |
| 3 | Sales | XYZ |
| 3 | Sales | XYZ |
+-------------+-----------+------+
I want to output only the groups that have unique teams greater than 3.
Only group 2 has this condition so the output is :
Expected Output:
+-------------+-----------+------+
| GroupNumber | TeamName | Goal |
+-------------+-----------+------+
| 2 | Design | XYZ |
| 2 | Sales | XYZ |
| 2 | technical | XYZ |
| 2 | Support | XYZ |
+-------------+-----------+------+
not sure how to utilize this in subquery
SELECT count(Distinct(TeamName))
FROM mytable
group by [GroupNumber]
HAVING COUNT(Distinct[TeamName])>3
Simply put it in a Subquery:
select *
from mytable
where [GroupNumber] in
(
SELECT [GroupNumber]
FROM mytable
group by [GroupNumber]
HAVING COUNT(Distinct[TeamName])>3
)
Please try
SELECT *
FROM mytable where GroupNumber in (select GroupNumber
FROM mytable group by TeamName
HAVING COUNT(TeamName)>3)

Concat multiple rows with dynamic table in SQL Server [duplicate]

This question already has answers here:
How to use GROUP BY to concatenate strings in SQL Server?
(22 answers)
Closed 6 years ago.
I have two tables where I joined both to get the first view, after that I'd like to do GROUP_CONCAT in one column, but we don't have this function in SQL Server.
So I tried some examples here, but was unsuccessful with my SQL. Examples found always use a table to generate GROUP_CONCAT, but I didn't find any example with a SQL result.
TableA:
| CityID | MasterID | Account |
+-----------------------------+
| 01 | 1234 | 1111 |
| 01 | 1234 | 2222 |
| 01 | 1234 | 3333 |
| 02 | 1234 | 4444 |
TableB:
| Account | Item | Price |
+------------------------+
| 1111 | A001 | 11,11 |
| 2222 | A001 | 11,11 |
| 3333 | A002 | 22,22 |
| 4444 | A002 | 22,22 |
| 5555 | A002 | 22,22 |
First SQL - Subselect:
SELECT *
FROM TableA, TableB
WHERE TableA.AccountID = TableB.AccountID
Output:
| CityID | MasterID | Account | Account | Item | Price |
+------------------------------------------------------+
| 01 | 1234 | 1111 | 1111 | A0001 | 11,11 |
| 01 | 1234 | 2222 | 2222 | A0001 | 11,11 |
| 01 | 1234 | 3333 | 3333 | A0002 | 22,22 |
| 02 | 1234 | 4444 | 4444 | A0002 | 22,22 |
Second SQL - final view:
SELECT
MasterID, GROUP_CONCAT(Item)
FROM
(SELECT *
FROM TableA, TableB
WHERE TableA.AccountID = TableB.AccountID) table01
Output:
| MasterID | Item |
+-----------------+
| 1234 | A0001,A002 |
This will give you expected result (I'm using Account as column name rather than AccountId as that's what you mentioned in table structure)
;WITH table01
AS
(
SELECT A.CityId,A.MasterId,A.Account Account1,B.Account Account2,B.Item,B.Price
FROM TableA A
INNER JOIN TableB B
ON A.Account = B.Account
)
SELECT A.MasterId,
STUFF(( SELECT ', ' + B.ITEM
FROM table01 B
WHERE B.MasterId = A.MasterId
group by B.MasterId,B.Item
FOR XML PATH('')
), 1, 2, '') Item
FROM table01 A
GROUP BY A.MasterId