How to group total amount spend based on both ID and name - sql

i have a table where
patientId | Units | Amount | PatientName
1234 | 1 | 20 |lisa
1111 | 5 | 10 |john
1234 | 10 | 200 |lisa
345 | 2 | 30 | xyz
i want to get ID in one column, then patient name then total amount spent by him on different items,
please note i have got patient name in the column above by doing a join on 2 tables using ID as the key
i am doing this to get this table
select t1.*,t2.name from table1 as t1 inner join table2 as t2
on t1.id = t2.id
then for adding i am trying to use the group by clause but that gives an error
please note i cannot use temp table in this, only need to do this using subquery, how to do it?

Are you looking for group by?
select t1.patientid, t2.patientname, sum(t1.amount)
from table1 t1 join
table2 t2
on t1.id = t2.id
group by t1.patientid, t2.patientname;

select t1.*,
t2.name
from table1 t1
inner join table2 t2
on t1.id = t2.id
group by t1.id, t2.name
What are table1 and table2 like? What's the error message?

Related

Microsoft SQL Server Conditional Joining based on 2 columns

I am looking to join 3 tables, all with the same data except one column is a different name (different date for each of the the 3 tables). The three tables look like the following. The goal is if a condition exists in table 1 AND/OR table 2 determine if a condition does or does not exist in table 3 for each individual id/condition. I'm currently left joining table 2 to table 1 but I'm aware that is not accounting for if a condition in table 2 exists that is not in table it is not being accounted for, anyways, any help would into this would be useful.
Table 1
id place Condition_2018
123 ABC flu
456 ABC heart attack
Table 2
id place Condition_2019
123 ABC flu
789 def copd
Table 3
id place Condition_2020
456 ABC heart attack
789 def copd
123 ABC flu
OUTPUT:
Table 2
id place Condition_2018 Condition_2019 Condition_2020
123 ABC flu flu flu
456 ABC heart attack null heart attack
789 def NULL copd copd
Thank you!
How about this (SQL Server syntax)...
SELECT
x.id
, x.place
, x.Condition_2018
, x.Condition_2019
, t3.Condition_2020
FROM (
SELECT
COALESCE(t1.id, t2.id) AS id
, COALESCE(t1.place, t2.place) AS place
, t1.Condition_2018
, t2.Condition_2019
FROM Table1 AS t1
FULL OUTER JOIN Table2 AS t2 ON t1.id = t2.id AND t1.place = t2.place
) AS x LEFT JOIN Table3 AS t3 ON x.id = t3.id AND x.place = t3.place
If your database supports full join, you can just do:
select
id,
place,
t1.condition_2018,
t2.condition_2019,
t3.condition_2020
from table1 t1
full join table2 t2 using(id, place)
full join table3 t3 using(id, place)
Otherwise, it is a bit more complicated: union all and aggregation is one method:
select
id,
place,
max(condition_2018) condition_2018,
max(condition_2019) condition_2019,
max(condition_2020) condition_2020
from (
select id, place, condition_2018, null condition_2019, null condition 2020 from table1
union all
select id, place, null, condition_2019, null from table2
select id, place, null, null, condition_2020 from table3
) t
group by id, place
You seem to want everything in Table3 and matches in the other two tables. That is just left joins:
select t3.id, t3.place,
t1.condition_2018, t2.condition_2019,
t3.condition_2020
from table3 t3 left join
table2 t2
on t3.id = t2.id and t3.place = t2.place left join
table1 t1
on t3.id = t1.id and t3.place = t1.place;
You need a full outer join of table1 and table2 and a left join to table3:
select
coalesce(t1.id, t2.id) id,
coalesce(t1.place, t2.place) place,
t1.Condition_2018,
t2.Condition_2019,
t3.Condition_2020
from table1 t1 full outer join table2 t2
on t2.id = t1.id
left join table3 t3
on t3.id = coalesce(t1.id, t2.id)
See the demo.
Results:
> id | place | Condition_2018 | Condition_2019 | Condition_2020
> --: | :---- | :------------- | :------------- | :-------------
> 123 | ABC | flu | flu | flu
> 456 | ABC | heart attack | null | heart attack
> 789 | def | null | copd | copd

how can i do the following query with Oracle SQL?

------------------
| **table 1** |
------------------
| 1 | 400 |
| 2 | 220 |
| 3 | 123 |
------------------
| **table 2** |
------------------
| 1 | 100 |
formula : table1 - table2 where table1.id=table2.id
------------------
| **Result** |
------------------
| 1 | 300 |
| 2 | 220 |
| 3 | 123 |
You want an outer join to get all rows from table_1 and the matching ones from table2
select t1.id, t1.val - coalesce(t2.val, 0) as result
from table_1 t1
left join table_2 t2 on t1.id = t2.id;
The coalesce(t2.val, 0) is necessary because the outer join will return null for those rows where no id exists in table_2 but t1.val - null would yield null
select t1.id,
nvl2(t2.val,t1.val-t2.val,t1.val) val
from t1,t2
where t1.id=t2.id(+)
order by t1.id;
Try this
select t1.col1, t1.col2-t2.col1 as balance from
table1 t1 left join table2 t2 on t1.col1=t2.col1
I don't the syntax in Oracle sql, but I can give the solution in mysql.
Consider the table with 2 columns:
id , value
SELECT table1.id, table1.value - table2.value
FROM table1, table2
WHERE table1.id=table2.id
OR
SELECT table1.id, table1.value
FROM table1, table2
WHERE NOT (table1.id =table2.id)
In some cases using scalar subquery caching could give better performance. It is on developer to compare execution plans and decide which query is the most appropriate.
with t1 (id, num) as
(
select 1, 400 from dual union all
select 2, 220 from dual union all
select 3, 123 from dual
),
t2(id, num) as
(
select 1, 100 from dual
)
select id,
num - nvl((select num from t2 where t2.id = t1.id), 0) result
from t1;
This is just to show you a different technique for solving problems in which you try to get data from several tables, but some may not have matching rows.
Using outer join in this case is in my opinion more logical.

Join two Tables with one have columns to rows

I have a table with this structure:
Table 1: ID(PK) | <other columns>
1 | otherdata
2 | otherdata
the other table, It´s a list of documents (PDF,DOC,etc) with a URL to download. these documents is stored in my network.
Table 2: ID | IDDOC | LINKDOC | INFO
1 | 1 | 'http://URL1' | 'Info1'
1 | 2 | 'http://URL2' | 'Info2'
2 | 1 | 'http://URL3' | 'Info3'
ID is the foreign key for Table 1,IDDOC is a foreign key to a 3rd table (below) that describe the document type:
Table 3: IDDOC | Name
1 | 'Contract'
2 | 'Notification'
I need to generate a query to join these tables and get a similar structure
ID | <SomeCollumsTable1> | NameDesc1 | NameURL1 | ... | NameDesc2 | NameURL2
Example output:
ID | <SomeCollumsTable1> | ContractDesc | ContractURL | NotificationDesc | NotificationURL
1 | otherdata | 'Info1' | 'http://URL1' | 'Info2' | 'http://URL2'
2 | otherdata | 'Info3' | 'http://URL3' | '' | ''
I.E. Generate many pairs Desc/URL as many records exits in "Table3". the sample data have 2 documents types and generate 4 columns.
Currently i have subquerys to each desired document, but sounds very inefficient for me, the query is big and new documents i add in "Table3" need change in the whole query and need to just adjust the Where clause to indicate why IDDOC´s need. (using a IN clause)
Or its better to manipulate this in my application (winforms/vb.net)?
The App generate a report in EXCEL format.
Please try the below query:
DECLARE #qu NVARCHAR(MAX), #pcol NVARCHAR(MAX)
SELECT #pcol= COALESCE(#pcol + ',','') + type FROM
(SELECT Name+N'URL' AS type FROM t3 UNION SELECT Name+N'Desc' AS type FROM t3 ) A
SET #qu=N'Select ID,b,c,'+ #pcol + N' FROM
(
SELECT t1.ID, t1.b,t1.c, t2.linkdoc as data,t3.Name +N''URL'' as Type FROM t1 LEFT JOIN t2 ON t1.ID=t2.ID
LEFT JOIN t3 ON t2.iddoc=t3.iddoc
UNION
SELECT t1.ID, t1.b, t1.c, t2.info as data, t3.Name +N''Desc'' as Type FROM t1 LEFT JOIN t2 ON t1.ID=t2.ID
LEFT JOIN t3 ON t2.iddoc=t3.iddoc
)S
PIVOT
(
MAX(data)
FOR Type IN ('+#pcol +N')) AS piv'
EXEC sp_executesql #qu
Here's a sql fiddle for you :
http://sqlfiddle.com/#!6/9fb46/1
EDIT:explanation added
So basically I am using PIVOT, except that PIVOT can be done on a
single column , in our case, either on URL or Desc columns. But we
need both these columns to be pivoted,so I used UNION to get both into
a single column data like below
SELECT t1.ID, t1.b,t1.c, t2.linkdoc as data,t3.Name +N'URL' as Type FROM t1 LEFT JOIN t2 ON t1.ID=t2.ID
LEFT JOIN t3 ON t2.iddoc=t3.iddoc
UNION
SELECT t1.ID, t1.b, t1.c, t2.info as data, t3.Name +N'Desc' as Type FROM t1 LEFT JOIN t2 ON t1.ID=t2.ID
LEFT JOIN t3 ON t2.iddoc=t3.iddoc
which I then used in PIVOT like this :
Select ID,b,c,[ContractURL],[ContractDesc],[NotificationURL],[NotificationDesc]
FROM
(
SELECT t1.ID, t1.b,t1.c, t2.linkdoc as data,t3.Name +N'URL' as Type FROM t1 LEFT JOIN t2 ON t1.ID=t2.ID
LEFT JOIN t3 ON t2.iddoc=t3.iddoc
UNION
SELECT t1.ID, t1.b, t1.c, t2.info as data, t3.Name +N'Desc' as Type FROM t1 LEFT JOIN t2 ON t1.ID=t2.ID
LEFT JOIN t3 ON t2.iddoc=t3.iddoc
)S
PIVOT
(
MAX(data)
FOR Type IN ([ContractURL],[ContractDesc],[NotificationURL],[NotificationDesc])
)piv
Now for making this dynamic I calculated all the unique columns from table t3 like
SELECT Name+N'URL' AS type FROM t3 UNION SELECT Name+N'Desc' AS type FROM t3

Joining two sql tables with a one to many relationship, but want the max of the second table

I am trying to join two tables one is a unique feature the seconds is readings taken on several dates that relate to the unique features. I want all of the records in the first table plus the most recent reading. I was able to get the results I was looking for before adding the shape field. By using the code
SELECT
Table1.Name, Table1.ID, Table1.Shape,
Max(Table2.DATE) as Date
FROM
Table1
LEFT OUTER JOIN
Table2 ON Table1.ID = table2.ID
GROUP BY
Table1.Name, Table1.ID, Table1.Shape
The shape field is a geometry type and I get the error
'The type "Geometry" is not comparable. It can not be use in the Group By Clause'
So I need to go about it a different way, but not sure how.
Below is a sample of the two tables and the desired results.
Table1
Name| ID |Shape
AA1 | 1 | X
BA2 | 2 | Y
CA1 | 3 | Z
CA2 | 4 | Q
Table2
ID | Date
1 | 5/27/2013
1 | 6/27/2014
2 | 5/27/2013
2 | 6/27/2014
3 | 5/27/2013
3 | 6/27/2014
My Desired Result is
Name| ID |Shape |Date
AA1 | 1 | X | 6/27/2014
BA2 | 2 | Y | 6/27/2014
CA1 | 3 | Z | 6/27/2014
CA2 | 4 | Q | Null
You can do the aggregation on Table2 in a CTE, finding the MAX(DATE) for each ID, and then join that result to Table1:
WITH AggregatedTable2(ID, MaxDate) AS
(
SELECT
ID, MAX(DATE)
FROM
Table2
GROUP BY
ID
)
SELECT
t1.ID, t1.Name, t1.Shape, t2.MaxDate
FROM
Table1 t1
LEFT JOIN
AggregatedTable2 t2 ON t1.ID = t2.ID
Try casting geometry as a varchar.
Select Table1.Name, Table1.ID, cast(Table1.Shape as varchar(1)) AS Shape, Max(Table2.DATE) as Date
FROM Table1 LEFT OUTER JOIN
Table2 ON Table1.ID = table2.ID
Group By Table1.Name, Table1.ID, cast(Table1.Shape as varchar(1))
Try this:
SELECT t1.Name
, t1.ID
, t1.Shape
, MAX(t2.Date) As Date
FROM Table1 AS t1
LEFT JOIN Table2 AS t2
ON t2.ID = t1.ID
GROUP
BY t1.Name
, t1.ID
, t1.Shape

Getting all the current effective records from a ORACLE table

I have two tables in oracle database
Table 1 say table1 with fields (id, name)
Records e.g.
###############
id | name
1 | Chair
2 | Table
3 | Bed
###############
and Table 2 say table2 with fields (id, table1_id, date, price)
##############################
id |table1_id| date | price
1 | 1 | 2013-09-09 | 500
2 | 1 | 2013-08-09 | 300
3 | 2 | 2013-09-09 | 5100
4 | 2 | 2013-08-09 | 5000
5 | 3 | 2013-09-09 | 10500
################################
What I want to achieve is to retrieve all the latest price of items from table 2
Result of SQL should be like
##############################
id |table1_id| date | price
1 | 1 | 2013-09-09 | 500
3 | 2 | 2013-09-09 | 5100
5 | 3 | 2013-09-09 | 10500
################################
I am able to run in mysql by following query
SELECT t2.id, t1.id, t1.name, t2.date, t2.price
FROM table1 t1 JOIN table2 t2
ON (t1.id = t2.table1_id
AND t2.id = (
SELECT id
FROM table2
WHERE table1_id = t1.id
ORDER BY table2.date DESC
LIMIT 1
));
but it's not working in ORACLE, Here i Need a query which can run on both server with minor modification
You may try this (shoud work in both MySQL and Oracle):
select t2.id, t2.table1_id, t2.dat, t2.price
from table1 t1 join table2 t2 on (t1.id = t2.table1_id)
join (select table1_id, max(dat) max_date
from table2 group by table1_id) tmax
on (tmax.table1_id = t2.table1_id and tmax.max_date = t2.dat);
This query may return several rows for the same table1_id and date if there are several prices in table2, like this:
##############################
id |table1_id| date | price
1 | 1 | 2013-09-09 | 500
2 | 1 | 2013-09-09 | 300
It's possible to change the query to retrieve only 1 row for each table1_id, but there should be some additional requirements (which row to choose in the above example)
if it doesn't matter then you may try this:
select max(t2.id) as id, t2.table1_id, t2.dat, max(t2.price) as price
from table1 t1 join table2 t2 on (t1.id = t2.table1_id)
join (select table1_id, max(dat) max_date
from table2 group by table1_id) tmax
on (tmax.table1_id = t2.table1_id and tmax.max_date = t2.dat)
group by t2.table1_id, t2.dat;
You can try this using GROUP BY instead, since you're not retrieving the product name from table1 except the product id (which is already in table2)
SELECT id,table1_id,max(date),price
FROM table2
GROUP BY id,table1_id,price
this is what you want :
select t2.id,t2.table1_id,t1.name,t2.pricedate,t2.price
from table1 t1
join
(
select id,table1_id, pricedate,price, row_number() over (partition by table1_id order by pricedate desc) rn
from table2
) t2
on t1.id = t2.table1_id
where t2.rn = 1