Create results grid from database tables: SQL - sql

I have a table which describes patients' medical symptoms which has the following structure.
Note that patient 1 and patient 2 have two symptoms.
| patientID | symptomName | SymptomStartDate | SymptomDuration |
|-----------|----------------|------------------|-----------------|
| 1 | Fever | 01/01/2020 | 10 |
| 1 | Cough | 02/01/2020 | 5 |
| 2 | ChestPain | 03/01/2020 | 6 |
| 2 | DryEyes | 04/01/2020 | 8 |
| 3 | SoreThroat | 05/01/2020 | 2 |
| 4 | AnotherSymptom | 06/01/2020 | 1 |
Using this data, I want to create a grid showing which symptoms each patient had, in the following format (with 1 indicating that the patient had that symptom and 0 indicating that the patient did not have that symptom)
| patientID | Fever | Cough | ChestPain | DryEyes | SoreThroat | AnotherSymptom |Headache|
|-----------|-------|-------|-----------|---------|------------|----------------|--------|
| 1 | 1 | 1 | 0 | 0 | 0 | 0 |0 |
| 2 | 0 | 0 | 1 | 1 | 0 | 0 |0 |
| 3 | 0 | 0 | 0 | 0 | 1 | 0 |0 |
| 4 | 0 | 0 | 0 | 0 | 0 | 1 |0 |
Note that none of the patients in this first table have headache but table 2 does have a column for headache filled with 0s. I have a list of all symptoms I want to include as columns in a separate table. (let's call that table symptom: The symptom table has only two columns : symptomName and symptomID)

Use a crosstab query:
TRANSFORM
Count(Symptoms.SymptomStartDate)
SELECT
Symptoms.PatientID
FROM
Symptoms
GROUP BY
Symptoms.PatientID
PIVOT
Symptoms.SymptomName
IN ('Fever','Cough','ChestPain','DryEyes','SoreThroat','AnotherSymptom','Headache');
Apply this format to the Format property of field SymptomStartDate:
0;;;0
Output:

Related

SQL Count depending on certain conditions

I have two tables.
One have userid and email (users table). The other have payments information (payments table) from the userid in users.
users
+--------+------------+
| Userid | Name |
+--------+------------+
| 1 | Alex T |
| 2 | Jeremy T |
| 3 | Frederic A |
+--------+------------+
payments
+--------+-----------+------------+----------+
| Userid | ValuePaid | PaidMonths | Refunded |
+--------+-----------+------------+----------+
| 1 | 1 | 12 | null |
| 1 | 20 | 12 | null |
| 1 | 20 | 12 | null |
| 1 | 20 | 1 | null |
| 2 | 1 | 1 | null |
| 2 | 20 | 12 | 1 |
| 2 | 20 | 12 | null |
| 2 | 20 | 1 | null |
| 3 | 1 | 12 | null |
| 3 | 20 | 1 | 1 |
| 3 | 20 | 1 | null |
+--------+-----------+------------+----------+
I want to count the PaidMonths taking in consideration the following rules:
If ValuePaid < 10 PaidMonths should be = 0.23 (even if in the column the value seen is any other mumber).
If Refund=1 the PaidMonths should be = 0.
Based on this when i join both tables by userid, and sum the PaidMonths based in the previousrules, i expect to see as result:
+--------+------------+------------+
| userid | Name | paidMonths |
+--------+------------+------------+
| 1 | Alex T | 25.23 |
| 2 | Jeremy T | 13.23 |
| 3 | Frederic A | 1.23 |
+--------+------------+------------+
Can you help me to achieve this in the most elegant way? Should a temporary table be used?
The following gives your desired results, using apply with case expression to map your values:
select u.UserID, u.Name, Sum(pm) PaidMonths
from users u join payments p on p.userid=u.userid
cross apply (values(
case
when valuepaid <10 then 0.23
when Refunded=1 then 0
else PaidMonths end
))x(pm)
group by u.UserID, u.Name
See Working Fiddle

How to write a sql script that cursors through a table and inserts into a different table

I am new to sql server i have the following table structure that contains more than a thousand rows.
But for example purposes this is what it would look like
Table Import
+------+---------+------------+------------+------------+------------+------------+
| Name | Code | SocksTotal | GlovesTotal| JeansTotal | ShirtsTotal| shoesTotal |
+------+---------+------------+------------+------------+------------+------------+
| OT | 45612 | 2 | 1 | 0 | 1 | 4 |
| OT | 1234 | 0 | 1 | 0 | 0 | 0 |
| US | 45896| 0 | 0 | 0 | 0 | 0 |
+------+---------+------------+------------+------------+------------+------------+
and a second table called Items follows
+------+---------+
| ID | Item |
+------+---------+
| 1 | socks |
| 2 | Gloves|
| 3 | Jeans |
| 4 | Shirts|
| 5 | shoes |
+------+---------+
from the above tables i need to write a script that would be inserted into a different table called ImportItems_Summary.
the expected output is
+------+---------+------------+------------+
| Id | Code | Items_id |Import_total|
+------+---------+------------+------------+
| 1 | 45612 | 1 | 2 |
| 2 | 45612 | 2 | 1 |
| 3 | 45612 | 4 | 1 |
| 4 | 45612 | 5 | 4 |
| 5 | 1234 | 2 | 1 |
+------+---------+------------+------------+
as you can see here that code 45612 now has 4 entries into the ImportItems_summary table where the items is not equal to 0 and the Items_id is linked to the Items table ID column.
How can i achieve the above output?.. I read up and saw a cursor might help but i am not sure how to implement this
One method uses cross apply to unpivot the columns of the unnormalized table to rows, then brings the items table with a join, and finally inserts in the target table:
insert into ImportItems_Summary (code, items_id, import_total)
select im.code, it.items_id, x.import_total
from import im
cross apply (values
('socks', sockstotal),
('gloves', glovestotal),
('jeans', jeanstotal),
('shirts', shirtstotal),
('shoes', shoestotal)
) x(item, import_total)
inner join items it on it.item = x.item

How to use recursive query to add columns to a select?

So I have an accounts table in witch row may or may not have a parent account (0 means it doesn't have a parent):
+----+-----------+
| id | parent_id |
+----+-----------+
| 1 | 2 |
| 2 | 0 |
| 3 | 1 |
| 4 | 3 |
| 5 | 4 |
+----+-----------+
I was trying to add the top 3 parents for each row, so I would get something like this:
+----+-----------+----------+----------+----------+
| id | parent_id | parent_1 | parent_2 | parent_3 |
+----+-----------+----------+----------+----------+
| 1 | 2 | 2 | null | null |
| 2 | 0 | null | null | null |
| 3 | 1 | 2 | 1 | null |
| 4 | 3 | 2 | 1 | 3 |
| 5 | 4 | 2 | 1 | 3 |
+----+-----------+----------+----------+----------+
I figured I can do it with recursive queries, but I haven't managed to build a working query.
Any help would be appreciated.

Exclude records from query where some columns are all not equal to a value

I am relatively new to ACCESS 2010 and to SQL. Having a bit of trouble figuring this one out.
I have a a query that returns a result from a table. I want to exclude any records where the values in columns A1-A4 all equal zero.
ex:
+----+----------+----+----+----+----+
| ID | CustName | A1 | A2 | A3 | A4 |
+----+----------+----+----+----+----+
| 1 | Ben | 0 | 0 | 0 | 0 |
| 2 | Tom | 0 | 0 | 0 | 1 |
| 3 | Jerry | 0 | 0 | 2 | 0 |
| 4 | Steve | 0 | 3 | 0 | 0 |
| 5 | Dave | 4 | 0 | 0 | 0 |
| 6 | Mike | 0 | 0 | 2 | 1 |
| 7 | Sheila | 0 | 3 | 2 | 1 |
| 8 | Jonesy | 4 | 3 | 2 | 1 |
+----+----------+----+----+----+----+
Using the table above as the source for the query, the only record I want to be excluded should be the very first record.
The SQL I am using for this query is
SELECT Test.CustName, Test.A1, Test.A2, Test.A3, Test.A4
FROM Test
WHERE (((Test.A1)<>0) AND ((Test.A2)<>0) AND ((Test.A3)<>0) AND ((Test.A4)<>0));
This SQL will only return records where all columns from A1-A4 are NOT equal to zero and only returns the final record. It should return record 2 - 7.
You want OR, not AND:
SELECT Test.CustName, Test.A1, Test.A2, Test.A3, Test.A4
FROM Test
WHERE (((Test.A1)<>0) OR ((Test.A2)<>0) OR ((Test.A3)<>0) OR ((Test.A4)<>0));
Use OR
SELECT t.CustName, t.A1, t.A2, t.A3, t.A4
FROM Test t
WHERE (((t.A1)!=0)
OR ((t.A2)!=0)
OR ((t.A3)!=0)
OR ((t.A4)!=0));
If those values are not negative you can also do
where A1+A2+A3+A3 > 0

Ask about query in sql server

i have table like this:
| ID | id_number | a | b |
| 1 | 1 | 0 | 215 |
| 2 | 2 | 28 | 8952 |
| 3 | 3 | 10 | 2000 |
| 4 | 1 | 0 | 215 |
| 5 | 1 | 0 |10000 |
| 6 | 3 | 10 | 5000 |
| 7 | 2 | 3 |90933 |
I want to sum a*b where id_number is same, what the query to get all value for every id_number? for example the result is like this :
| ID | id_number | result |
| 1 | 1 | 0 |
| 2 | 2 | 523455 |
| 3 | 3 | 70000 |
This is a simple aggregation query:
select id_number, sum(a*b)
from t
group by id_number
I'm not sure what the first column is for.