IF ( Count(*) > 1) - sql

I am trying to look through two tables TableA and TableB get print out the TableA.ID of any that show more than 1 count. TableA looks like this:
ID | Code
------------
1 | A
2 | B
3 | C
Table B Looks like
ID | AID | EffectiveDate | ExpirationDate
------------------------------------------------
1 | 1 | 2012-01-01 | 2012-12-31
2 | 1 | 2012-01-01 | 2012-12-31
3 | 2 | 2012-01-01 | 2012-12-31
4 | 3 | 2012-01-01 | 2012-12-31
The Query I am using looks like this:
DECLARE #MoreThanOne varchar(250)
SET #MoreThanOne = ''
IF((SELECT COUNT(*) FROM TableA
WHERE EXISTS(
SELECT TableB.ID
,TableB.EffectiveDate
,TableB.ExpirationDate
FROM TableB
WHERE TableB.AID = TableA.ID
and GETDATE() Between TableB.EffectiveDate and TableB.ExpirationDate
)
GROUP BY TableA.Code) > 1)
BEGIN
--SET #MoreThanOne = #MoreThanOne + TableA.Code + CHAR(10)
END
PRINT #MoreThanOne
I know that my nested Query works when reworked it will print the counts for all in the unique codes in TableA.
I know that I can not use what I commented out because i don't have access to TableA.Code.
My question is there another way to do this or how can I get access to TableA.Code for the Message MoreThanOne.
Thanks For the help!

This query will get you the codes for all AIDs that are duplicated in table B:
SELECT Code
FROM TableA
WHERE AID IN
(
SELECT AID
FROM TableB
GROUP BY AID
HAVING COUNT(*) > 1
)
You may also wish to add the WHERE condition that have in your stored procedure to the inner select.

Try this
SELECT TableA.ID, TableA.Code, Count(*) As Cnt
FROM TableB, TableA
WHERE TableB.AID = TableA.ID
and GETDATE() Between TableB.EffectiveDate and TableB.ExpirationDate
GROUP BY TableA.ID, TableA.Code
HAVING COUNT(*) > 1

You can do this very simply, with no join:
SELECT tableb.AID
FROM TableB
WHERE GETDATE() Between TableB.EffectiveDate and TableB.ExpirationDate
group by tableb.AID
having count(*) > 1
This simply aggregates tableB by AID, returning the values with more than one record. You only need to join to TableA if you want the code as well.

This should do you:
select Code = a.Code ,
Frequency = count(*)
from table_a a
join table_b b on b.aid = a.id
and current_timestamp between b.EffectiveDate and b.ExpirationDate
group by a.Code
having count(*) > 1
order by 2 desc -- order in descending sequence by frequency
1 -- then ascending sequence by code

Related

SQL Exclude Row if Specific Value Exists Within Joined Field

I am trying to write an SQL query that will allow me to exclude a record from TableA if it has at least one match against TableB.
I have written some code, as below, that almost gets me what I need -
SELECT a.ID,
a.OPEN_DT,
b.LINKCREATED,
b.RULE__ID
FROM TableA a
LEFT JOIN TableB b
ON a.ROW_WID = b.A_ROW_WID
WHERE EXTRACT(YEAR FROM a.OPEN_DT) >= '2013'
AND NOT EXISTS (SELECT *
FROM TableB
WHERE A_ROW_WID = a.ROW_WID
AND EXTRACT(YEAR FROM b.CREATED) >= '2017')
;
Table A
ROW_WID | ID | OPEN_DT
---------------------------------
1 | A | 2013-01-01
2 | B | 2014-01-01
3 | C | 2017-01-01
Table B
RULE_ID | A_ROW_WID | LINKCREATED
---------------------------------
1 | A | 2014-01-01
2 | A | 2017-01-01
3 | B | 2017-01-01
The query above would return 1 row for ROW_WID = 1, 1 row for ROW_WID = 2 and nothing for ROW_WID = 3.
I would like my query to exclude ROW_WID=1 altogether because there is one row in TableB that has the year 2017.
I hope this question is clear, but let me know if not.
-EDIT-
Expected result would look like this -
ID | OPEN_DT | LINKCREATED | RULE_ID
C | 2017-01-01 | NULL | NULL
As ID 'C' from TableA has no link in TableB.
If there were an entry in A that had any links in B prior to 2017, they would be returned. Just not any with a TableB entry >= 2017.
Your issue is that you aren't checking for the max created date in the NOT EXISTS:
SELECT a.ID,
a.OPEN_DT,
b.LINKCREATED,
b.RULE__ID
FROM TableA a
LEFT JOIN TableB b
ON a.ROW_WID = b.A_ROW_WID
WHERE EXTRACT(YEAR FROM a.OPEN_DT) >= '2013'
AND NOT EXISTS (SELECT 'NE'
FROM TableB B2
WHERE A_ROW_WID = a.ROW_WID
AND B2.LINKCREATED= (SELECT MAX(BE.LINKCREATED) FROM TableB BE WHERE B2.A_ROW_WID=BE.A_ROW_WID)
AND EXTRACT(YEAR FROM b2.CREATED) >= '2017')
Try using not in:
SELECT a.ID,
a.OPEN_DT,
b.LINKCREATED,
b.RULE__ID
FROM TableA a
LEFT JOIN TableB b
ON a.ROW_WID = b.A_ROW_WID
WHERE EXTRACT(YEAR FROM a.OPEN_DT) >= '2013'
AND b.rule_id not in (select rule_id from TableB where A_ROW_WID in (SELECT
A_ROW_WID
FROM TableB
WHERE EXTRACT(YEAR FROM b.CREATED) >= '2017')a)b

left join not giving correct output

I am having 2 table
tableA
Accountid
-----------
10
11
12
tableB
Accountid | Date |
--------------------------------------------
10 | 2016-02-02 |
11 | 2016-02-02 |
11 | 2016-02-02 |
15 | 2016-02-03 |
I am expecting the output like
Accountid | ID |
------------------------------------
10 | 10 |
11 | 11 |
12 | NULL |
I am running this query
select A.accountid,b.accountid as ID
from tableA as A
left join tableB as B on a.accountid=b.accountid
where b.date between '2016-02-02' and '2016-02-02'
but it is giving me the output as, I am not sure where am I going wrong
Accountid | ID |
-----------------------------------
10 | 10 |
11 | 11 |
I am using MSSQL database.
When any field of the right table of a left join is occurred in WHERE clause then this join will behave like INNER JOIN
To get expected result your query should be like this
select A.accountid,b.accountid as ID
from tableA as A
left join tableB as B on a.accountid=b.accountid and
b.date between '2016-02-02' and '2016-02-02'
Try this:
select A.accountid,b.accountid as ID
from tableA as A left join tableB as B on a.accountid=b.accountid
where b.date is null or b.date between '2016-02-02' and '2016-02-02'
The reason is, for AccountID 12 b.date is effectively null (because there's no row in tableB). Therefore you'll only get a result for that row if you allow date to be null in the query.
If b does not exist (id = 12) your where clause return false .
if you want to see the row with id=12 you must include your test (b.date between '2016-02-02' and '2016-02-02') with your "ON" clause :
select A.accountid,b.accountid as ID from tableA as A left join tableB as B
on a.accountid=b.accountid and b.date between '2016-02-02' and '2016-02-02'
the reason is because the WHERE clause of your select is executed after the LEFT JOIN
so, first sql server will extract the data as you expect, with the row 12-NULL,
and then it will be filtered out and removed from output by your WHERE clause
you can move the date filter on JOIN condition as suggested by #JaydipJ and #RémyBaron
or filter the tableB before the JOIN this way:
select A.accountid,b.accountid as ID
from tableA as A
left join (
select *
from tableB
where b.date between '2016-02-02' and '2016-02-02'
) as B on a.accountid=b.accountid

How do show a result table from two 'select'? SQL

I have 2 queries:
First query:
select TableB.name, count(TableB.name) from TableB group by TableB.name
result:
name | count
Jack | 2
Marry| 1
and
Second query:
select DISTINCT TableA.kName, TableA.Value from TableA inner join TableB
ON
TableA.kName=TableB.name
result:
kName | Value
Jack | 1
Marry | 3
But I need result table:
kName | Value | newColumn
Jack | 1 | 2
Marry | 3 | 1
where the newColumn is result of first query, How can to do it? help, please.
maybe:
select DISTINCT TableA.kName, TableA.value,
(select TableB.name, count(TableB.name) from TableB group by TableB.name)
AS
newColumn from TableA inner join TableB ON TableA.kName=TableB.name
but this is not work :(
Try this query
SELECT tableB.name, tableA.value, count(tableB.name) as newColum FROM tableB
JOIN tableA ON tableB.name = tableA.kname
GROUP BY tableB.name,tableA.value
select kname, value, "newColumn"
from
(
select name, count(name) as "newColumn"
from tb
group by name
) tb
inner join
(
select distinct kname, value
from ta
) ta ta.kname = tb.name

ORACLE - remove from result set if two or more "same" records found

ID | NAME | REFERENCE | STATUS
-------------------------------
1 | name1 | 123 | 0
2 | name1 | 123 | 1
3 | name2 | 111 | 0
4 | name3 | 222 | 0
5 | name5 | 555 | 1
Let's say I have this table TABLE1. I need a select statement that will only find records with STATUS=0, but if "same" record exists with STATUS=1 (like those records with ID 1 and 2)
So, query must find only third and fourth record.
Based on your suggested results, I am reading your question as "find only records with status = 0 where the same name/reference combination doesn't have a record with status = 1".
One way you can do this is with a not exists clause:
select t.*
from table t
where status = 0 and
not exists (select 1
from table t2
where t2.name = t.name and
t2.reference = t.reference and
t2.status = 1
);
Try this query out:
SELECT A.*
FROM TABLE1 A
LEFT JOIN TABLE1 B ON
A.ID = B.ID AND
A.NAME = B.NAME AND
A.REFERENCE = B.REFERENCE AND
B.STATUS = 1
WHERE A.STATUS = 0
AND B.REFERENCE IS NULL
The NULL check on B.REFERENCE in the WHERE clause basically ensures that there was no matching record found in the LEFT JOIN (you could just use B.ID or B.NAME also).
MINUS can be used to get the value with Status both 0 but not 1.
SELECT ID, Name, Reference, Status
FROM Table1
WHERE (Name, Reference) IN (SELECT Name, Reference
FROM Table1
WHERE Status = 0
MINUS
SELECT Name, Reference
FROM Table1
WHERE Status = 1)
SELECT * FROM TABLE WHERE NAME NOT IN
(
SELECT NAME FROM
TABLE
GROUP BY NAME
HAVING COUNT(DISTINCT STATUS)>1
) AND STATUS='0';

How to create view that combine multiple row from 2 tables?

I want to create view that combine data from two tables, sample data in each table is like below.
SELECT Command for TableA
SELECT [ID], [Date], [SUM]
FROM TableA
Result
ID | Date | SUM
1 | 1/1/2010 | 2
1 | 1/2/2010 | 4
3 | 1/3/2010 | 6
SELECT Command for TableB
SELECT [ID], [Date], [SUM]
FROM TableB
Result
ID | Date | SUM
1 | 1/1/2010 | 5
1 | 2/1/2010 | 3
1 | 31/1/2010 | 2
2 | 1/2/2010 | 20
I want output like below
ID | Date | SUMA | SUMB
1 | 1/1/2010 | 2 | 10
1 | 1/2/2010 | 4 | 0
2 | 1/2/2010 | 0 | 20
3 | 1/3/2010 | 6 | 0
How can I do that on SQL Server 2005?
Date information be vary, as modify in table.
Try this...
SELECT
ISNULL(TableA.ID, TableB.ID) ID,
ISNULL(TableA.Date, TableB.Date),
ISNULL(TableA.Sum,0) SUMA,
ISNULL(TableB.Sum, 0) SUMB
FROM
TableA FULL OUTER JOIN TableB
ON TableA.ID = TableB.ID AND TableA.Date = TableB.Date
ORDER BY
ID
A full outer join is what you need because you want to include results from both tables regardless of whether there is a match or not.
I usually union the two queries together and then group them like so:
SELECT ID, [Date], SUM(SUMA) As SUMA, SUM(SUMB) AS SUMB
FROM (
SELECT ID, [Date], SUMA, 0 AS SUMB
FROM TableA
UNION ALL
SELECT ID, [Date], 0 As SUMA, SUMB
FROM TableB
)
GROUP BY ID, [Date]
SELECT
ISNULL(a.ID, b.ID) AS ID,
ISNULL(a.Date, b.Date) AS Date,
ISNULL(a.SUM, 0) AS SUMA,
ISNULL(b.SUM, 0) AS SUMB,
FROM
TableA AS a
FULL JOIN
TableB AS b
ON a.ID = b.ID
AND a.Date = b.Date;
It's not obvious how you want to combine the two tables. I think this is what you're after, but can you confirm please?
TableA.Date is the most important field; if a given date occurs in TableA then it will be included in the view, but not if it only occurs in TableB.
If a date has records in TableA and TableB and the records have a matching ID, they are combined into one row in the view with SUMA being taken from TableA.Sum and SUMB being TableA.Sum * TableB.Sum (e.g. Date: 01/01/2010, ID: 1) (e.g. Date: 01/03/2010 ID: 3).
If a date has records in TableA and TableB with different IDs, the view include these records separately without multiplying the Sum values at all (e.g. Date 02/01/2010, ID: 1 and ID: 2)