Store row values as new column before group by - sql

Anyone know how I can group by, but keep a distinct column? I messed around with UNPIVOT but couldnt find a good explanation to help me write my code. Anyone have a solution?
I have data that looks like this:
acct contact email phone
1 44 abc NULL
1 33 NULL 123
2 2 xxx NULL
2 22 NULL 456
I use
select acct,max(email) as email, max(phone) as phone from my_table
group by acct
to wind up with this:
acct email phone
1 abc 123
2 xxx 456
but my end goal is to group by and create a separate contact column for phone and email like this:
acct contact_email email phone contact_phone
1 44 abc 123 33
2 2 xxx 456 22

You appears to want simple aggregation :
select acct,
max(case when phone is null then contact end) as contact_email,
max(email) as email, max(phone) as phone,
max(case when email is null then contact end) as contact_phone
from table t
group by acct;

Try Below, might be it will help, without sub query and without group
SELECT t1.acct,t1.contact contact_email,t1.email, t2.phone,t2.contact contact_phone FROM my_table t1 inner join my_table t2 on t1.acct=t2.acct
where t1.email is not null and t2.phone is not null

Related

Getting records from 2 tables with common an uncommon columns

Below is similar example of the issue I have:
if I have this table 1:
Patient ID
Name
Check in Date
order name
preformed by
1
Jack
12/sep/2002
xray
Dr.Amal
2
Nora
15/oct/2002
ultrasound
Dr.Goerge
1
Jack
13/nov/2003
Medicine
Dr.Fred
table 2:
Patient ID
Name
Check in Date
order name
1
Jack
14/Jun/2002
xray 2
2
Nora
15/oct/2002
ultrasound
1
Jack
13/nov/2003
Medicine
3
Rafael
13/nov/2003
Vaccine
The result I need is as the following:
Name
Check in Date
order name
preformed by
Jack
12/sep/2002
xray
Dr.Amal
Nora
15/oct/2002
ultrasound
Dr.Goerge
Jack
13/nov/2003
Medicine
Dr.Fred
Jack
14/Jun/2002
xray 2
Null
Rafael
13/nov/2003
Vaccine
Null
If you noticed the result I need is all records of table 1 and all records of table 2 with no duplication and joining the same common fields and adding 'Preformed by' column from Table 1. I tried using 'UNION' as the following:
SELECT Name, Check_in_Date, order_name,preformed_by
FROM table1
UNION
SELECT Name, Check_in_Date, order_name,''
FROM table2
the result I get is 2 records for each patient with the same date one with preformed by one with null as the following:
Name
Check in Date
order name
preformed by
Jack
12/sep/2002
xray
Dr.Amal
Nora
15/oct/2002
ultrasound
Dr.Goerge
Nora
15/oct/2002
ultrasound
Null
Jack
13/nov/2003
Medicine
Dr.Fred
Jack
13/nov/2003
Medicine
null
Jack
14/Jun/2002
xray 2
Null
Rafael
13/nov/2003
Vaccine
Null
If the same ID has same check in date in both table it must return the preformed by of table 1 not null How can I do this?
Thank you.
What you need is a FULL JOIN matching by those three columns along with NVL() function in order to bring the values
from table2 which return null from table1 such as
SELECT NVL(t1.name,t2.name) AS name,
NVL(t1.check_in_date,t2.check_in_date) AS check_in_date,
NVL(t1.order_name,t2.order_name) AS order_name,
t1.preformed_by
FROM table1 t1
FULL JOIN table2 t2
ON t1.name = t2.name
AND t1.check_in_date = t2.check_in_date
AND t1.order_name = t2.order_name
or another method uses UNION to filter out duplicates and then applies an OUTER JOIN such as
SELECT tt.name, tt.check_in_date, tt.order_name, t1.preformed_by
FROM (
SELECT name, check_in_date, order_name FROM table1 UNION
SELECT name, check_in_date, order_name FROM table2
) tt
LEFT JOIN table1 t1
ON t1.name = tt.name
AND t1.check_in_date = tt.check_in_date
AND t1.order_name = tt.order_name
Demo

SQL Query, GROUP/COUNT issue with INNER JOIN

I've got a data set composed primarily of dates, IDs, and addresses, that looks a bit like this:
datadate id address
20150801 Bob 123
20150801 Bob 123
20150801 Dan 345
20150801 Dan 456
20150801 Dan 567
20150801 George 234
20150801 Jim 123
20150801 Jim 123
20150801 John 678
20150801 John 123
20150802 Tom 123
20150802 Tom 234
20150802 Tom 345
My goal is to write a query which identifies any IDs which are associated with multiple distinct addresses for a specific date (or date range). I want the query results to give me the name and distinct addresses. So, for this data set, the results I'd like to see would look like this, for date 8/1/2015:
datadate id address
20150801 Dan 345
20150801 Dan 456
20150801 Dan 567
20150801 John 678
20150801 John 123
The query I've worked up so far is this, but it's not really working for me:
SELECT a.[datadate], a.[id], a.[address], b.[count1]
FROM table1 AS a INNER JOIN (SELECT [id], COUNT([address]) as [count1] FROM table1 GROUP BY [id] having count1 > 1 ) AS b ON a.[id]=b.[id]
WHERE a.[datadate] = '20150801'
ORDER BY a.[id], a.[address];
Any suggestions?
Just modifying your existing query a little bit, you can change your having to count(distinct address) and then joining back to the table to get your address values like this:
SELECT t.datadate
,t.id
,t1.address
FROM (
SELECT datadate
,id
,count(DISTINCT address) address
FROM test
WHERE datadate = '20150801'
GROUP BY datadate,id
HAVING count(DISTINCT address) > 1
) t
INNER JOIN test t1 ON t.datadate = t1.datadate
AND t.id = t1.id;
I tested this on SQL Server, but should be similar in MS-Access as well.
SQL Fiddle Demo
Edit
I just read your question again and it appears you want all duplicates. In which case I would use exists to see if another row with the same id but a different address exists.
select * from mytable t1
where datadate = '20150801'
and exists (
select 1 from mytable t2
where t2.id = t1.id
and t2.address <> t1.address
and t2.datadate = t1.datadate
)

Find count from specific table by specific filter sql server

I am Having table like this:
id candid candname status date time location jobcode
1 12 hhhhhhhhhh Introduce 2014-05-21 14:0 NewYork 10JN
3 12 hhhhhhhhhh Reject 2014-05-21 15:0 AM London 10JN
4 12 hhhhhhhhhh Interview 2014-05-21 15:0 PM Chicago 10JN
5 11 Pinky Bare Introduce 2014-05-21 65:6 India 10JN
6 11 Pinky Bare Interview 2014-05-21 4:56 AM 10JN
7 13 chetan Tae Introduce 2014-05-21 4:54 AM Nagpur faOl
8 13 chetan Tae Interview 2014-05-21 3:45 Pune faOl
9 14 manisha mane Introduce 2014-05-21 3:33 PM Pune faOl
10 18 ranju gondane Introduce 2014-05-28 3:44 Nagpur AQW-06
12 18 ranju gondane Interview 2014-05-28 5:45 45454 AQW-06
13 18 ranju gondane Reject 2014-05-28 43:43 rsds AQW-06
14 19 vandanna rai Introduce 2014-05-28 7:7 yyyr AQW-06
if i use query
SELECT COUNT(*) FROM [tablename]
WHERE
(jobcode='AQW-06')
AND
([status] <> 'Interview' AND [status] <> 'Reject'
AND
[status] <> 'ON-Hold' AND [status] <> 'Hire')
I get count 2 for introduce candidates..
if the candidate is interviewd after introduce, it will not counted as Introduce
I want the count of Introduce, interviewd, rejected candidates of specofic jobcode
Please help me for this.
You can try
select status, count(*)
from [tablename]
where jobcode = 'AQW-06'
group by status
Edit: You can try use something like this
select count(x.candid) numofcandidates, x.statusnum
from
(select candid, max(case when status = 'Reject' then 3
when status = 'Interview' then 2
when status = 'Introduce' then 1 end) statusnum
from [tablename] t
where jobcode = 'AQW-06'
group by candid) x
group by x.statusnum;
What I actually did is to "translate" the status to a number, so I can use the highest status first. All you need to do then it to "translate" back the statusnum to the values of your table. In my opinion I would use a statusnum in my table directly
Try this:
;with reftable as
(select 1 'key', 'Introduce' 'val'
union
select 2 'key', 'Interview' 'val'
union
select 3 'key', 'Rejected' 'val'
),
cte as
(select e.candid, e.[status], row_number() over (partition by e.candid order by r.[key] desc) rn
from yourtable e
inner join reftable r on e.[status] = r.val
where e.[status] in ('Introduce','Interview','Rejected')
and e,jobcode = 'AQW-06')
select [status], count([status])
from cte
where rn = 1
group by [status]
Basically, we assign a numeric value to your text status to allow sorting. In the over clause, we sort by this numeric value in descending order to get the highest status of a candidate as you describe. Then, we just count the number of occurrences of each status.
Note that you can extend this to include values for status like 'Hire'. To do this, you will need to add it to the list in reftable with appropriate numeric value, and also add it to the filter in cte.
I want the count of Introduce, interviewed, rejected candidates of specific jobcode
The query below will return the results you need:
SELECT SUM(t.IsIntroduction) AS CountOfIntroductions,
SUM(t.IsInterview) AS CountOfInterviews,
SUM(t.IsRejected) AS CountOfRejections
FROM (
SELECT id,
CASE WHEN Status = 'Introduce' THEN 1 ELSE 0 END AS IsIntroduction,
CASE WHEN Status = 'Interview' THEN 1 ELSE 0 END AS IsInterview,
CASE WHEN Status = 'Reject' THEN 1 ELSE 0 END AS IsRejected
FROM [Tablename]
WHERE JobCode = 'AQW-06'
) AS t
Sample at this SQL Fiddle.

Combine rows into one result and add results as different values in SQL

I have a table (people) that include the following information:
id cert_id type name
1 123 owner Paul
2 123 seller George
3 123 buyer steve
4 456 owner micheal
I also have a table (items) that includes the following:
id cert_id item_name
1 123 staples
2 123 cheese
3 123 iguanas
4 456 pie
Basically, what I want to do is have the results as the following:
cert_id owner_name seller_name buyer_name item_name
123 Paul George steve staples, cheese, iquanas
456 micheal pie
So far I have been able to use MAX(CASE WHEN people.type='owner' THEN people.name END) AS owner_name, but I cannot get the seller name to append to the other row ('im not sure if this is even possible via the SQL statement or if I should do some formatting with the results afterwards. Any advice on combining rows would be helpful, or a simple "not possible" would let me know what the limitations are.
Thanks in advance!
You should be able to use the following query to get the result:
select p.cert_id,
max(case when p.type = 'owner' then p.name end) owner_name,
max(case when p.type = 'seller' then p.name end) seller_name,
max(case when p.type = 'buyer' then p.name end) buyer_name,
array_agg(distinct i.item_name) Items
from people p
inner join items i
on p.cert_id = i.cert_id
group by p.cert_id;
See SQL Fiddle with Demo
This can be accomplished using INNER JOIN or LEFT-OUTER-JOIN...

SQL Group By Help Required

I have a table named People in the following format:
Date | Name.
When I count the people by Grouping By Name with
Select Date, Name, count(*)
From People
Group By Date, Name;
Will give the following
Date Name count(*)
10 Peter 25
10 John 30
10 Mark 25
11 Peter 15
11 John 10
11 Mark 5
But I would like the following result:
Date Peter John Mark
10 25 30 25
11 15 10 5
Is this possible? This is a simple example of a more complicated database. If someone helps me in solving this problem I will use the concept to implement it in my table
Thanks!
Select Date
, count(case when Name = 'Peter' then 1 else null end)
, count(case when Name = 'John' then 1 else null end)
, count(case when Name = 'Mark' then 1 else null end)
From People
Group By Date;
another option different from turbanoff's if, for some reason, you find yourself in a situation that you cant apply a group by:
Select distinct(P.Date),
(select count(*) from People where date=p.date and name='Peter') as Peter,
(select count(*) from People where date=p.date and name='John') as John,
(select count(*) from People where date=p.date and name='Mark') as Mark
From People P