SQL Server 2008 R2 Grouping - sql-server-2008-r2

Here is the script I have.
select jt.exempt_status as ExemptStatus, COUNT(*) as ExemptCount
from employee as e
join job_title as jt
on e.job_title = jt.job_title
group by jt.exempt_status
When executed it displays
ExemptStatus ExemptCount
-----------------------------
E 2
N 5
What I need it to display without changing the values in the jt.exempt_status field is.
ExemptStatus ExemptCount
-----------------------------
Exempt 2
Non-Exempt 5

You can use a CASE expression to format your values when selecting them:
select CASE jt.exempt_status
WHEN 'E' THEN 'Exempt'
WHEN 'N' THEN 'Non-Exempt'
END
as ExemptStatus, COUNT(*) as ExemptCount
from employee as e
join job_title as jt
on e.job_title = jt.job_title
group by jt.exempt_status

Related

T-SQL select all IDs that have value A and B

I'm trying to find all IDs in TableA that are mentioned by a set of records in TableB and that set if defined in Table C. I've come so far to the point where a set of INNER JOIN provide me with the following result:
TableA.ID | TableB.Code
-----------------------
1 | A
1 | B
2 | A
3 | B
I want to select only the ID where in this case there is an entry for both A and B, but where the values A and B are based on another Query.
I figured this should be possible with a GROUP BY TableA.ID and HAVING = ALL(Subquery on table C).
But that is returning no values.
Since you did not post your original query, I will assume it is inside a CTE. Assuming this, the query you want is something along these lines:
SELECT ID
FROM cte
WHERE Code IN ('A', 'B')
GROUP BY ID
HAVING COUNT(DISTINCT Code) = 2;
It's an extremely poor question, but you you probably need to compare distinct counts against table C
SELECT a.ID
FROM TableA a
GROUP BY a.ID
HAVING COUNT(DISTINCT a.Code) = (SELECT COUNT(*) FROM TableC)
We're guessing though.

Subsetting records that contain multiple values in one column

In my postgres table, I have two columns of interest: id and name - my goal is to only keep records where id has more than one value in name. In other words, would like to keep all records of ids that have multiple values and where at least one of those values is B
UPDATE: I have tried adding WHERE EXISTS to the queries below but this does not work
The sample data would look like this:
> test
id name
1 1 A
2 2 A
3 3 A
4 4 A
5 5 A
6 6 A
7 7 A
8 2 B
9 1 B
10 2 B
and the output would look like this:
> output
id name
1 1 A
2 2 A
8 2 B
9 1 B
10 2 B
How would one write a query to select only these kinds records?
Based on your description you would seem to want:
select id, name
from (select t.*, min(name) over (partition by id) as min_name,
max(name) over (partition by id) as max_name
from t
) t
where min_name < max_name;
This can be done using EXISTS:
select id, name
from test t1
where exists (select *
from test t2
where t1.id = t2.id
and t1.name <> t2.name) -- this will select those with multiple names for the id
and exists (select *
from test t3
where t1.id = t3.id
and t3.name = 'B') -- this will select those with at least one b for that id
Those records where for their id more than one name shines up, right?
This could be formulated in "SQL" as follows:
select * from table t1
where id in (
select id
from table t2
group by id
having count(name) > 1)

Getting error while retrieving data from a sub query and using that data source in another sub query above that

select id,proc_name,p_date,p_no,p_count
from (
(Select id,proc_name,p_date,p_no from aa) x
join
(select id,count(p_no) p_count from aa group by mrn) y
on x.id=y.id
) a
FROM (select id,proc_name,p_date,p_no from zz) aa
getting the error code 42601 at the position of FROM (in upper case).
A SELECT statement can only have one FROM clause.
Instead of using multiple FROM clauses, you should JOIN the tables.
There is no need to have two SELECTs from table aa, you can do that with a single SELECT using window functions:
SELECT id, proc_name, p_date, p_no,
count(p_no) OVER (PARTITION BY mrn) p_count
FROM aa;
You didn't tell over which columns you want to join aa and zz, but your statement could look something like this:
SELECT a.id, a.proc_name, a.p_date, a.p_no, a.p_count
FROM
(SELECT id, proc_name, p_date, p_no,
count(p_no) OVER (PARTITION BY mrn) p_count
FROM aa) a
JOIN zz
ON <join condition for a and zz>;

Inner join within update statement in PostgreSQL

I have table called temp_table which consist of following rows:
cola colb result
----------------
p4 s1 0
p8 s1 0
p9 s1 0
p5 f1 0
p8 f1 0
Now I need to update result column with the count(*) of colb. For which i am trying the following query:
update tem_table
set result = x.result
from tem_table tt
inner join(select colb,count(*) as result from tem_table group by colb) x
on x.colb = tt.colb;
And selecting distinct colb and result from temp_table:
select distinct colb,result from tem_table;
Getting output:
colb result
-----------
s1 3
f1 3
But the expected output is:
colb result
-----------
s1 3
f1 2
I am not getting where I am getting wrong in my query? Please help me.Thanks
You should not repeat the table to be updated in the from clause. This will create a cartesian self join.
Quote from the manual:
Note that the target table must not appear in the from_list, unless you intend a self-join (in which case it must appear with an alias in the from_list)
(Emphasis mine)
Unfortunately UPDATE does not support explicit joins using the JOIN keyword. Something like this should work:
update tem_table
set result = x.result
from (
select colb,count(*) as result
from tem_table
group by colb
) x
where x.colb = tem_table.colb;

Eliminating matching values in a SQL result set

I have a table with a list of transactions (invoices and credits) and I need to get a list of all the rows where the invoices and credits don't match up.
eg
user product value
bill ThingA 200
jim ThingA -200
sue ThingB 100
liz ThingC 50
I only want to see the third and fourth rows, as the values of the others match off.
I can do this if I select product, sum(value)
...
group by product
having sum(value) <> 0
which works well, but I want to return the user name as well.
As soon as I add the user to the select, I need to group by it as well, which messes it up as the amounts don't match up by user AND product.
Any ideas ? I am using MS SQL 2000...
Cheers
You can do like this:
SELECT tab2.user, product, sum_val
FROM
(SELECT product, SUM(value) sum_val
FROM your_table
GROUP BY product HAVING SUM(value) <> 0) tab1
INNER JOIN your_table tab2
ON tab1.product = tab2.product
#LolCoder solution is good, but given a context where you have "Thing B" with a "100" value by both "sue" and "liz", you could be able to retrieve the following resultset with my query :
| product | value | users |
+----------------------------+
| Thing B | 200 | sue, liz |
Here is the query :
select product
,sum(value) as value
,Stuff(( select ',' + convert(varchar(40), SQ.user)
from YourTable SQ
where Q.product = SQ.product
for xml path('')
), 1, 1, '') as users
from YourTable Q
group by Q.product