I am very new to SQL and never did anything complex like this. Any help would be appreciated.
I have following data in the table:
ID - TAG
1 - U
1 - N
1 - U
1 - N
1 - U
My output needs to be
ID - U - N
1 - 3 - 2
Basically my output needs to count N's and U's for the ID and produce a single row for that ID.
Thanks for your time.
SELECT
ID,
COUNT(CASE WHEN TAG = 'U' THEN 1 END) AS [U],
COUNT(CASE WHEN TAG = 'N' THEN 1 END) AS [N]
FROM
someTable
GROUP BY
ID
UPDATE:
Another poster (see below) points out that I used square brackets where some RDBMSs require double quotes.
In MySQL this is simplier than you think :)
select id,
sum(if(tag = 'U', 1, 0)) as U,
sum(if(tag = 'N', 1, 0)) as N
from table1
group by id
Basically, for each id you get you create a new column (U and N) which will have a 1 or a 0 based on whether tag has value 'U' or 'N'. This results in something like this:
+----+---+---+
| ID | U | N |
+----+---+---+
| 1 | 1 | 0 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
+----+---+---+
Now, all we have to do is group by ID and sum all values from U and N, and we get:
+----+---+---+
| ID | U | N |
+----+---+---+
| 1 | 3 | 2 |
+----+---+---+
Hope this helps.
Related
I have to perform a query where I can count the number of distinct codes per Id.
|Id | Code
------------
| 1 | C
| 1 | I
| 2 | I
| 2 | C
| 2 | D
| 2 | D
| 3 | C
| 3 | I
| 3 | D
| 4 | I
| 4 | C
| 4 | C
The output should be something like:
|Id | Count | #Code C | #Code I | #Code D
-------------------------------------------
| 1 | 2 | 1 | 1 | 0
| 2 | 3 | 1 | 0 | 2
| 3 | 3 | 1 | 1 | 1
| 4 | 2 | 2 | 1 | 0
Can you give me some advise on this?
This answers the original version of the question.
You are looking for count(distinct):
select id, count(distinct code)
from t
group by id;
If the codes are only to the provided ones, the following query can provide the desired result.
select
pvt.Id,
codes.total As [Count],
COALESCE(C, 0) AS [#Code C],
COALESCE(I, 0) AS [#Code I],
COALESCE(D, 0) AS [#Code D]
from
( select Id, Code, Count(code) cnt
from t
Group by Id, Code) s
PIVOT(MAX(cnt) FOR Code IN ([C], [I], [D])) pvt
join (select Id, count(distinct Code) total from t group by Id) codes on pvt.Id = codes.Id ;
Note: as I can see from sample input data, code 'I' is found in all of Ids. Its count is zero for Id = 3 in the expected output (in the question).
Here is the correct output:
DB Fiddle
Let's assume I have a report that displays an ID and VALUE from different tables
| ID | VALUE |
|----|-------|
1 | 1 | 1 |
2 | 1 | 0 |
3 | 1 | 1 |
4 | 2 | 0 |
5 | 2 | 0 |
My goal is to display this table with grouped IDs and VALUEs. My rule to grouping VALUEs would be "If VALUE contains atleast one '1' then display '1' otherwise display '0'".
My current SQL is (simplified)
SELECT
TABLE_A.ID,
CASE
WHEN TABLE_B.VALUE = 1 OR TABLE_C.VALUE NOT IN (0,1,2,3)
THEN 1
ELSE 0
END AS VALUE
FROM TABLE_A, TABLE_B, TABLE_C
GROUP BY
TABLE_A.ID
(CASE
WHEN TABLE_B.VALUE = 1 OR TABLE_C.VALUE NOT IN (0,1,2,3)
THEN 1
ELSE 0
END)
The output is following
| ID | VALUE |
|----|-------|
1 | 1 | 1 |
2 | 1 | 0 |
3 | 2 | 0 |
Which is half way to the output I want
| ID | VALUE |
|----|-------|
1 | 1 | 1 |
2 | 2 | 0 |
So my Question is: How do I extend my current SQL (or change it completely) to get my desired output?
If you are having only 0 and 1 as distinct values in FOREIGN_VALUE column then using max() function as mentioned by HoneyBadger in the comment will fulfill your requirement.
SELECT
ID,
MAX(FOREIGN_VALUE) AS VALUE
FROM (SELECT
ID,
CASE WHEN FOREIGN_VALUE = 1
THEN 1
ELSE 0
END AS FOREIGN_VALUE
FROM TABLE,
FOREIGN_TABLE)
GROUP BY
ID;
Assuming value is always 0 or 1, you can do:
select id, max(value) as value
from t
group by id;
If value can take on other values:
select id,
max(case when value = 1 then 1 else 0 end) as value
from t
group by id;
Obviously there are a bunch of questions about ROW_NUMBER in MS Access and the usually response is that it does not exist but instead to use a COUNT(*) to create something similar. Unfortunately, doing so does not give me the results that I need.
My data looks like:
RID | QID
---------
1 | 1
1 | 2
1 | 3
1 | 3
2 | 1
2 | 2
2 | 2
What I am trying to get at is a unique count over RID and QID so that my query output looks like
RID | QID | SeqID
------------------
1 | 1 | 1
1 | 2 | 1
1 | 3 | 1
1 | 3 | 2
2 | 1 | 1
2 | 2 | 1
2 | 2 | 2
Using the COUNT(*) I get:
RID | QID | SeqID
------------------
1 | 1 | 1
1 | 2 | 2
1 | 3 | 3
1 | 3 | 3
2 | 1 | 1
2 | 2 | 2
2 | 2 | 2
My current query is:
SELECT
d.RID
,d.QID
,(SELECT
COUNT(*)
FROM
Data as d2
WHERE
d2.RID = d.RID
AND d2.QID < d.QID) + 1 AS SeqID
FROM
Data as d
ORDER BY
d.RID
,d.QID
Any help would be greatly appreciated.
As Matt's comment implied, the only way to make this work is if you have some column in your table that can uniquely identify each row.
Based on what you have posted, you don't seem to have that. If that's the case, consider adding a new auto increment numeric column that can serve that purpose. Let's pretend that you call that new column id.
With that in place, the following query will work:
select t.rid, t.qid,
(select count(*)
from data t2
where t2.rid = t.rid
and t2.qid = t.qid
and t2.id <= t.id) as SeqID
from data t
order by t.rid, t.qid
SQLFiddle Demo
Using SQL Server 2008, I want to query a table like so:
| ID | Number
-------------
| 1 | 0
| 2 | 0
| 3 | 1
| 4 | 0
| 5 | 0
| 6 | 1
| 7 | 1
| 8 | 1
The result should be the same table with an additional column that counts.
The method of counting is: if the number in "number" equals to 1 - increment the counter by one for the next line.
An example of result for the provided table:
| ID | Number | Counter
-----------------------
| 1 | 0 | 1
| 2 | 0 | 1
| 3 | 1 | 1
| 4 | 0 | 2
| 5 | 0 | 2
| 6 | 1 | 2
| 7 | 1 | 3
| 8 | 1 | 4
How can this be achieved?
select [ID], [Number],
isnull(1+(select sum([Number]) from Table1 t2 where t2.ID<t1.Id),1)
from Table1 t1
SQL Fiddle to test
This is not too hard to do. What you are looking for is very much like the running total, which you get with sum and a windowing clause.
select id, num, 1 + sum(num) over (order by id) - num as counter
from mytable
order by id;
Here is an SQL fiddle: http://sqlfiddle.com/#!4/958e2a/1.
You can use recursive select too but it is a bit complicated but if you insert other numbers which are greater than 1 it work fine:
with tab(id,number,counter,rn) as
(select t.*,1 as counter,1 as rn from table1 t where id = 1
union all
select t.*,case when t.number = 1 then counter + 1 else counter end as counter,
rn + 1 as rn from table1 t,tab where t.id = tab.rn + 1),
tab2 as (select id,number,counter from tab)
select id,number,case when number = 1 then counter - 1
else counter end as counter from tab2;
SQL Fiddle
Hy all,
I need a little help with writing a select...the problem is the following:
I have the following tables:
help
+----+-------+---------+
| id | title | content |
+----+-------+---------+
| 1 | a | acont |
| 2 | b | bcont |
+----+-------+---------+
helptag
+----+------+
| id | name |
+----+------+
| 1 | atag |
| 2 | btag |
+----+------+
helphelptag(join table)
+--------+-----------+
| helpid | helptagid |
+--------+-----------+
| 1 | 1 |
| 1 | 2 |
| 2 | 2 |
+--------+-----------+
I need to select those helps, whish has the ids i give.
So for example if i give tag_id 2, than both help 1 and 2
but if i give tag_id 1 and 2, than only help 1.
I've tried leftjoin, with the ids IN[tag_ids], but it gives back both helps if i give 1 and 2.
This is an example of a "set-within-sets" query. I like to solve this using aggregation and having clause. For your first question:
select helpid
from helphelptag
group by helpid
having sum(case when helptagid = 2 then 1 else 0 end) > 0;
For the second, just add another condition:
having sum(case when helptagid = 2 then 1 else 0 end) > 0 and
sum(case when helptagid = 1 then 1 else 0 end) > 0;
Each condition counts the number of rows that match a given condition.