Query to count the entries - sql

I have two tables like this.
A B
1 12
2 13
3 12
4 13
5 15
B C
12 APPLE
13 ORANGE
14 MANGO
15 BANANA
I need output as below...
count(A) B C
2 12 APPLE
2 13 ORANGE
0 14 MANGO
1 15 BANANA
I have written the query using joins but I am stuck at displaying the count as zero in case of empty value.

Use a left join to get the values of table2 even if there are no records for them in table1
select T2.B, T2.C, count(T1.A)
from table2 T2
left join table1 T1 on T1.B = T2.B
group by T2.B, T2.C

Try this:
SELECT COUNT(T1.A) as Cnt,T2.B,T2.C
FROM Table2 T2 LEFT JOIN
Table1 T1 ON T1.B=T2.B
GROUP BY T2.B,T2.C
Result:
CNT B C
2 12 APPLE
1 15 BANANA
0 14 MANGO
2 13 ORANGE
See result in SQL Fiddle.

Just to give you another option. You don't need a join, as you only want to show table2 records along with another value which you can get in a sub-query.
select (select count(*) from table1 where table1.B = table2.B) as cnt, B, C
from table2
order by B;

There are other ways to do it (using subquery), but I would use this following one:
-- SETUP
CREATE TABLE #TABLE1 (A INT, B INT);
CREATE TABLE #TABLE2 (B INT, C CHAR(10));
INSERT #TABLE1
SELECT 1, 12 UNION ALL
SELECT 2, 13 UNION ALL
SELECT 3, 12 UNION ALL
SELECT 4, 13 UNION ALL
SELECT 5, 15
INSERT #TABLE2
SELECT 12, 'APPLE' UNION ALL
SELECT 13, 'ORANGE' UNION ALL
SELECT 14, 'MANGO' UNION ALL
SELECT 15, 'BANANA'
-- query
SELECT COUNT(qty.A), dsc.B, dsc.C
FROM #TABLE2 dsc
LEFT JOIN #TABLE1 qty ON (dsc.B = qty.B)
GROUP BY dsc.B, dsc.C
ORDER BY dsc.B, dsc.C;

DECLARE #TABLE1 TABLE (A INT, B INT)
INSERT INTO #TABLE1 VALUES
(1, 12),
(2, 13),
(3, 12),
(4, 13),
(5, 15)
DECLARE #TABLE2 TABLE (B INT, C VARCHAR(20))
INSERT INTO #TABLE2 VALUES
(12,'APPLE'),
(13,'ORANGE'),
(14,'MANGO'),
(15,'BANANA')
SELECT t2.C
,ISNULL(COUNT(t1.B), 0) total_Count
FROM #TABLE2 t2 LEFT JOIN #TABLE1 t1
ON t2.B = t1.B
GROUP BY t2.C
C total_Count
APPLE 2
BANANA 1
MANGO 0
ORANGE 2

Related

count of row by row from another table holding some conditions on both tables in sql

There are two tables Table1 and Table2
A B C S
a 1 21 Summer
b 2 22 Summer
c 3 34 Summer
D E F S
a 1 21 Summer
d 5 22 Summer
f 2 34 Summer
I wanted to fetch all columns of Table first and count of column F from table second based on conditions such as column B OF table first is less than values of column E of table second.
I tried this query
select a.*,
(select count(F) from Table2 JOIN Table1 on table1.S=table2.S where table1.B<table2.E ) AS Cnt
from Table1 a
However it is giving me same count for all rows which is incorrect
I need count based on condition fulfilled.
This will work
DECLARE #T1 TABLE (A Varchar(10), B INT, C INT, S Varchar(10))
DECLARE #T2 TABLE (D Varchar(10), E INT, F INT, S Varchar(10))
INSERT INTO #T1 VALUES
('a', 1, 21,'Summer'),
('b', 2 ,22,'Summer'),
('c', 3, 34,'Summer')
INSERT INTO #T2 VALUES
('a', 1, 21,'Summer'),
('d', 5 ,22,'Summer'),
('f', 2 ,34,'Summer')
SELECT
T1.A,T1.B,T1.C,T1.S,
COUNT(T2.S) as Counts
FROM #T1 T1
left JOIN #T2 T2
ON T1.S = T2.S AND T1.B < T2.E
GROUP BY T1.A,T1.B,T1.C,T1.S
Output
A B C S Counts
a 1 21 Summer 2
b 2 22 Summer 1
c 3 34 Summer 1
select *,
(select count(F)
from T2
where T1.S = T2.S AND T1.B < T2.E
) as Cnt from T1
I think you just want a correlated subquery:
select a.*,
(select count(t2.F)
from Table2 t2
where a.S = t2.S and t1.B < t2.E
) as Cnt
from Table1 a

I would like to update table using merge and my table source will use cross join

I have a Table1:
IdT1 : 11, 12, 13
IdT1Group : 30,30,30
Table2:
IdT2 : 1, 2, 3, 4
IdT1 : 11, 11, 12, 12
Detail : A, B, A, B
AND User Defined Table Type #T2:
IdT2 : 1, 2, 3
IdT1 : 11,11,11
Detail: A,B,C
I would like to Update Table2 to be:
IdT2 : 1,2,5, 3,4,6, 7,8,9
IdT1 : 11,11,11, 12,12,12, 13,13,13
Detail : A,B,C, A,B,C, A,B,C
So, I was Use Merge in StoredProcedure:
;WITH Table2
AS (SELECT Table2.* FROM Table2 INNER JOIN Table1 ON Table2.IdT1 = Table1.IdT1 AND IdT1Group = 30)
MERGE INTO Table2 AS tblTarget
USING (SELECT #T2.*, T1Item.IdT1 AS T1Id FROM #T2 CROSS JOIN Table1 where IdT1Group = 30)
AS tblSource
ON tblTarget.IdT1 = tblSource.T1Id And tblTarget.IdT2 = tblSource.IdT2
WHEN MATCHED THEN
UPDATE
SET Detail = tblSource.Detail
WHEN NOT MATCHED BY SOURCE THEN
DELETE
WHEN NOT MATCHED BY TARGET THEN
INSERT (IdItem, IdT2, Detail)
VALUES (tblSource.IdT1,
tblSource.IdT2, tblSource.Detail);
But after i tried my code, my table2 become:
IdT2 : 1,2,5, 6,7,8, 9,10,11
IdT1 : 11,11,11, 12,12,12, 13,13,13
Detail: A,B,C, A,B,C, A,B,C
This is what should it be:
IdT2 : 1,2,5, 3,4,6, 7,8,9
IdT1 : 11,11,11, 12,12,12, 13,13,13
Detail : A,B,C, A,B,C, A,B,C
I think the output should look like follows because one of the values get deleted. further i think you have a identity column or a incremental value in the Table2 for IdT2.
when you delete an item the increased value will not get deducted.
output
IdT2 IdT1 Detail
----------- ----------- -------
1 11 A
2 11 B
5 11 C
3 12 C
6 12 A
7 12 B
8 13 A
9 13 B
10 13 C
SQL statement (NOTE: Created # tables instead of physical tables to get this going)
create table #Table1
(
IdT1 int , IdT1Group int
)
insert into #Table1
select 11 IdT1,30 IdT1Group union all
select 12 IdT1,30 IdT1Group union all
select 13 IdT1,30 IdT1Group
create table #Table2
(
IdT2 int identity(1,1), IdT1 int , Detail varchar(100)
)
insert into #Table2
SELECT 11 IdT1 ,'A' Detail union all
SELECT 11 ,'B' union all
SELECT 12 ,'A' union all
SELECT 12 ,'B'
declare #T2 table
(
IdT2 int , IdT1 int , Detail varchar(100)
)
insert into #T2
SELECT 1 IdT2 , 11 IdT1 ,'A' Detail union all
SELECT 2 , 11 ,'B' union all
SELECT 3 , 12 ,'C'
MERGE INTO #Table2 AS tblTarget
USING (SELECT T2.*, T1Item.IdT1 AS T1Id FROM #T2 T2 CROSS JOIN #Table1 T1Item where IdT1Group = 30)
AS tblSource
ON tblTarget.IdT1 = tblSource.T1Id And tblTarget.IdT2 = tblSource.IdT2--tblTarget.IdT1 = tblSource.T1Id And tblTarget.IdT2 = tblSource.IdT2
WHEN MATCHED THEN
UPDATE
SET Detail = tblSource.Detail
WHEN NOT MATCHED BY SOURCE THEN
DELETE
WHEN NOT MATCHED BY TARGET THEN
INSERT (IdT1, Detail)
VALUES (tblSource.T1Id,
tblSource.Detail);
select * from #Table2
order by 2,1
drop table #Table1
drop table #Table2

SQL Statement with 3 select statements

I am trying to combine the data of three tables but running into a minor issue.
Let's say we have 3 tables
Table A
ID | ID2 | ID3 | Name | Age
1 2x 4y John 23
2 7j Mike 27
3 1S1 6HH Steve 67
4 45 O8 Carol 56
Table B
| ID2 | ID3 | Price
2x 4y 23
7j 8uj 27
x4 Q6 56
Table C
|ID | Weight|
1 145
1 210
1 240
2 234
2 110
3 260
3 210
4 82
I want to get every record from table A of everyone who weighs 200 or more but they cannot be in table B. Table A and C are joined by ID. Table A and B are joined by either ID2 or ID3. ID2 and ID3 don't both have to necessarily be populated but at least 1 will. Either can be present or both and they will be unique. So expected result is
3 | 1S1 | 6HH | Steve| 67
Note that a person can have multiple weights but as long as at least one record is 200 or above they get pulled.
What I have so far
Select *
From tableA x
Where
x.id in (Select distinct y.id
From tableA y, tableC z
Where y.id = z.id
And z.weight >= '200'
And y.id not in (Select distinct h.id
From tableA h, tableB k
Where (h.id2 = k.id2 or h.id3 = k.id3)))
When I do this it seems to ignore the check on tableB and I get John, Mike and Steve. Any ideas? Sorry it's convoluted, this is what I have to work with. I am doing this in oracle by the way.
This sounds like exists and not exists. So a direct translation is:
select a.*
from tableA a
where exists (select 1 from tableC c where c.id = a.id and c.weight >= 200) and
not exists (select 1 from tableB b where b.id2 = a.id2 or b.id3 = a.id3);
Splitting the or into two separate subqueries can often improve performance:
select a.*
from tableA a
where exists (select 1 from tableC c where c.id = a.id and c.weight >= 200) and
not exists (select 1 from tableB b where b.id2 = a.id2) and
not exists (select 1 from tableB b where b.id3 = a.id3);
Here's what I came up with.
SELECT DISTINCT
A.ID,
A.ID2,
A.ID3,
A.Name,
A.Age
FROM
A
LEFT OUTER JOIN C ON C.ID = A.ID
LEFT OUTER JOIN B ON
B.ID2 = A.ID2
OR B.ID3 = A.ID3
WHERE
C.Weight >= 200
AND B.Price IS NULL
BELOW is test data
CREATE TABLE A
(
ID INT,
ID2 VARCHAR(3),
ID3 VARCHAR(3),
Name VARCHAR(10),
Age INT
);
INSERT INTO A VALUES (1, '2x', '4y', 'John', 23);
INSERT INTO A VALUES (2, '7j', NULL , 'Mike', 27);
INSERT INTO A VALUES (3, '1S1', '6HH', 'Steve', 67);
INSERT INTO A VALUES (4, '45', 'O8', 'Carol', 56);
CREATE TABLE B
(
ID2 VARCHAR(3),
ID3 VARCHAR(3),
Price INT
);
INSERT INTO B VALUES ('2x', '4y', 23);
INSERT INTO B VALUES ('7j', '8uj', 27);
INSERT INTO B VALUES ('x4', 'Q6', 56);
CREATE TABLE C
(
ID INT,
Weight INT
);
INSERT INTO C VALUES (1, 145);
INSERT INTO C VALUES (1, 210);
INSERT INTO C VALUES (1, 240);
INSERT INTO C VALUES (2, 234);
INSERT INTO C VALUES (2, 110);
INSERT INTO C VALUES (3, 260);
INSERT INTO C VALUES (3, 210);
INSERT INTO C VALUES (4, 82);
Select a.id, a.id2, a.id3
From table_a a
Left join table_c c on a.id = c.id
Where c.weight >=200
And not exists
(Select 1
From table_b b
Where a.id = b.id2
Or a.id = b.id3
);
I was beating to the answers, but I used INNER JOIN on tables a and c and a NOT EXISTS on table b.
--This first section is creating the test data
with Table_A (id, id2, id3, Name, age) as
(select 1, '2x', '4y', 'John', 23 from dual union all
select 2, '7j', null, 'Mike', 27 from dual union all
select 3, '1S1', '6HH', 'Steve', 67 from dual union all
select 4, '45', 'O8', 'Carol', 56 from dual),
Table_B(id2, id3, price) as
(select '2x', '4y', 23 from dual union all
select '7j', '8uj', 27 from dual union all
select 'x4', 'Q6', 56 from dual),
Table_C(id, weight) as
(select 1, 145 from dual union all
select 1, 210 from dual union all
select 1, 240 from dual union all
select 2, 234 from dual union all
select 2, 110 from dual union all
select 3, 260 from dual union all
select 3, 210 from dual union all
select 4, 82 from dual)
--Actual query starts here
select distinct a.*
from table_a a
--join to table c, include the weight filter
inner join table_c c on (a.id = c.id and c.weight >= 200)
where not exists -- The rest is the NOT EXISTS to exclude the values in table b
(select 1 from table_b b
where a.id2 = b.id2
or a.id3 = b.id3);

union of two table - intersection of two table

I have following tables;
A B A B
_____ _____
1 t 7 a
2 r 5 d
3 e 3 e
4 f 9 a
5 d 10 c
6 s 11 a
7 a
And, output should be ;
A B
_____
1 t
2 r
4 f
6 s
9 a
10 c
11 a
In other words I want really different thing. I can only tell with this figure, take a look at. I want (A union B).
How can I do that ?
This query will do it. It loads up all the records from both tables, then displays all those that exist once
SELECT
A, B
FROM
(SELECT A, B FROM TABLE1
UNION ALL
SELECT A, B FROM TABLE2)
AS COMBINED
GROUP BY
A, B
HAVING
COUNT(*) = 1
ORDER BY A;
SELECT f.A, f.B
FROM firstTable f
LEFT JOIN secondTable s ON (f.A = s.A)
WHERE (s.A IS NULL)
UNION
SELECT s.A, s.B
FROM firstTable f
RIGHT JOIN secondTable s ON (f.A = s.A)
WHERE (f.A IS NULL)
SELECT iResult.*
FROM
(SELECT A, B
FROM tableA
WHERE A NOT IN
(SELECT Distinct A FROM tableB)
UNION
SELECT A, B
FROM tableB
WHERE A NOT IN
(SELECT Distinct A FROM tableB)) as iResult
SELECT A, B
FROM Table1
UNION
SELECT A, B
FROM Table2
EXCEPT
SELECT t1.A, t1.B
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.A = t2.A AND t1.B = t2.B
Edit Removed prior "solution" since I realised it's the same as the one proposed by Gary.
(select a, b from table_1 minus
select a, b from table_2) union
(select a, b from table_2 minus
select a, b from table_1);
This seemed to work with the followoing data on Oracle:
create table table_1 (
a number,
b varchar(2)
);
create table table_2 (
a number,
b varchar(2)
);
insert into table_1 values (1 ,'t');
insert into table_1 values (2 ,'r');
insert into table_1 values (3 ,'e');
insert into table_1 values (4 ,'f');
insert into table_1 values (5 ,'d');
insert into table_1 values (6 ,'s');
insert into table_1 values (7 ,'a');
insert into table_2 values (7 ,'a');
insert into table_2 values (5 ,'d');
insert into table_2 values (3 ,'e');
insert into table_2 values (9 ,'a');
insert into table_2 values (10 ,'c');
insert into table_2 values (11 ,'a');
Simply
SELECT a, b FROM table1 UNION SELECT a, b FROM table2;

SQL: Making a 'computation row'

I have a table that looks like this
TYPE | A | B | C | ... | Z
one | 4 | 4 | 4 | ... | 4
two | 3 | 2 | 2 | ... | 1
And I wanted to insert a row with a computation (row one minus row two):
TYPE | A | B | C | ... | Z
one | 4 | 4 | 4 | ... | 4
two | 3 | 2 | 2 | ... | 1
delta| 1 | 2 | 2 | ... | 3
I was thinking of a SQL command that looks like
(select A from table where type=one) - (select A from table where type=two)
Down side is, it's too long and I also have to do that for all the columns (A-Z) and that's quite a lot.
I'm sure there's a more elegant way of doing this.
PS:
The sequence of my code looks like this btw:
// I'm inserting the data from a RawTable to a TempTable
INSERT one
INSERT two
INSERT delta
INSERT three
INSERT four
INSERT delta
...
INSERT onehundredone
INSERT onehundredtwo
INSERT delta
I have added an ID column with identity to your temp table. You can use that to figure out what rows should be grouped.
create table YourTable
(
ID int identity primary key,
[TYPE] varchar(20),
A int,
B int,
C int
)
insert into YourTable ([TYPE], A, B, C)
select 'one', 4, 4, 4 union all
select 'two', 3, 2, 2 union all
select 'three', 7, 4, 4 union all
select 'four', 3, 2, 2 union all
select 'five', 8, 4, 4 union all
select 'six', 3, 2, 2
select T.[TYPE], T.A, T.B, T.C
from
(
select
T.ID,
T.[TYPE],
T.A,
T.B,
T.C
from YourTable as T
union all
select
T2.ID,
'delta' as [TYPE],
T1.A-T2.A as A,
T1.B-T2.B as B,
T1.C-T2.C as C
from YourTable as T1
inner join YourTable as T2
on T1.ID = T2.ID-1 and
T2.ID % 2 = 0
) as T
order by T.ID, case T.[TYPE] when 'delta' then 1 else 0 end
Result:
TYPE A B C
-------------------- ----------- ----------- -----------
one 4 4 4
two 3 2 2
delta 1 2 2
three 7 4 4
four 3 2 2
delta 4 2 2
five 8 4 4
six 3 2 2
delta 5 2 2
Sorting on column C from first row in group:
select T.[TYPE], T.A, T.B, T.C
from
(
select
T1.ID,
T1.[TYPE],
case T1.ID % 2 when 1 then T1.C else T2.C end as Sortorder,
T1.A,
T1.B,
T1.C
from YourTable as T1
left outer join YourTable as T2
on T1.ID = T2.ID+1
union all
select
T2.ID,
'delta' as [TYPE],
T1.C as Sortorder,
T1.A-T2.A as A,
T1.B-T2.B as B,
T1.C-T2.C as C
from YourTable as T1
inner join YourTable as T2
on T1.ID = T2.ID-1 and
T2.ID % 2 = 0
) as T
order by T.Sortorder, T.ID, case T.[TYPE] when 'delta' then 1 else 0 end
I'm not aware of any way to do this "easily" (i.e. without having to specify every column), I can't come up with any way to do it easily, so I'll go on the record as saying that it can't be done. Easily.
The non-easy way would be to build dynamic code--something that loops through the database metadata, builds a string containing the statement(s) to execute your desired routine column by column, and then execute that string. You really want to avoid this whenever possible.
One shortcut, if you just need to build a procedure or function that does this (i.e. build once run many), you could copy the list of columns into a spreadsheet (Excel), build out the highly-repetitive statements using forumlas that reference the column names, and then copying the results back. (This is much simpler to do than it is to explain.)
I have no idea why you're doing this, but the way I'd approach it is:
insert into table
select 'delta',
t1.a - t2.a,
t1.b - t2.b
.....
from table t1,
table t2
where t1.type = 'one'
and t2.type = 'two'
You would have to run this query immediately after inserting "one" and "two", then re-run it after inserting "three" and "four". Nasty nasty nasty.
If you can re-name the columns in some way, or create a numerical column, you could run it in a single query.
When you replace one for 1, two for 2, and so on, then maybe this sql could work:
INSERT INTO PodMays
SELECT
"Delta", A.A-B.A, A.B-B.B, A.C-B.C, A.D-B.D, A.E-B.E
FROM
(
SELECT TOP 1
*
FROM
(SELECT TOP 2 * FROM PodMays WHERE Type <> "Delta" ORDER BY Type DESC)
ORDER BY
Type ASC
) AS A,
(
SELECT TOP 1
*
FROM
(SELECT TOP 2 * FROM PodMays WHERE Type <> "Delta" ORDER BY Type DESC)
ORDER BY
Type DESC
) AS B