MS SQL Script to find rows where value does not exist - sql

I have a situation where I have in one table record 'a' which have order number 0 and also record 'a' but with order number 1 - this is correct.
i also have record 'b' which has order number 1 and there is no row for record 'b' where order number = 0. - this is not correct.
I need to create a script which will find all records where order number = 1 but order number 0 doesn't exist. Can you guys help with this?
i cannot use simple:
SELECT DISTINCT record FROM tablename WHERE order_number <> 0
because it will give me also record 'a' which i don't want to have in results.
I was thinking about using Not Exists function but it always compares 2 tables where i have all records in one table.
Regards

Using Not Inin Where will eliminate 'a' and will give only 'b'
Try this:-
SELECT DISTINCT record FROM tablename WHERE order_number <> 0
and record not in (Select record from tablename WHERE order_number = 0);
hope this helps:-)

Related

Return one record per criteria

I am struggling with a solution for getting one record per criteria.
In the attached example, I would like to get one record per "nbr".
I have started with this, but I cannot get what I need.
SELECT t2.*,
CASE
WHEN t2.duplicate_flag=1 AND (t2.country=t2.country_active OR t2.country=t2.country_inactive) THEN 1 ELSE t2.duplicate_flag END nbr_match
FROM
(SELECT t1.*,
CASE d.duplicate WHEN 1 THEN 1 ELSE 999 END duplicate_flag
FROM [Sheet1$] t1
JOIN
(SELECT nbr, COUNT(*) as duplicate
FROM [Sheet1$]
GROUP BY nbr) d
ON t1.nbr=d.nbr) t2
As I said, I would like to get one record per "nbr".
If I have one record per "nbr" it is OK and I will mark it with "1". For the others that have duplicates (count(*)>1), I will mark as "99" and then to modify these "99" based on conditions to get one record.
These are the rules that I have to follow in order to get one record per "nbr":
1. IF "country"="country_active" return me that row (per "nbr")
2. ELSEIF "country"="country_inactive" return me that row
3. If I have two the same countries between the "country" and the "country_active" THEN look at the MAX "expiration_date_active" OR MAX "expiration_date_inactive" and return me that record.
4. IF there is no match between "country"<>"country_active" AND "country"<>"country_inactive" return the column with the MAX date either from "expiration_date_active" OR "expiration_date_inactive"
The final table or output should look like:
Thank you in advance for help.
Original data:
Does this provide the results you would expect ?
WITH ListOfNbr AS (SELECT DISTINCT nbr FROM [Sheet1$])
SELECT t2.*
FROM ListOfNbr t1
CROSS APPLY (
SELECT TOP 1 *
FROM [Sheet1$]
WHERE nbr = t1.nbr
ORDER BY
CASE WHEN country = country_active THEN 1 ELSE 0 END DESC,
CASE WHEN country = country_inactive THEN 1 ELSE 0 END DESC,
expiration_date_active DESC,
expiration_date_inactive DESC
) t2

SQL select either table 1 or table 2

I have two following queries. How can I modify this into single query? The result should be true if either query returns data, and false otherwise:
select custId from customer where customerId=3425632456 and custPhone='5653663251';
select accountnumber from account where accountId=524526 and accountPhone='5653663251';
Here custPhone=accountPhone
I think that you want exists:
select case
when exists (select custId from customer where customerId=3425632456 and custPhone='5653663251')
then 1
when exists (select accountnumber from account where accountId=524526 and accountPhone='5653663251')
then 1
else 0
end res
from dual
This query always return a single row, with a single column called res. If any of the subqueries returns something, then res has value 1, else 0.
As a performance bonus for using case, the second subquery is not executed if the first succeeds (this is called short-circuit evaluation). If your queries are time consuming, this can be interesting; make sure to put the less expensive query first.
If you actually want to return the values, then that's different. One option is union all:
select custId from customer where customerId=3425632456 and custPhone='5653663251'
union all
select accountnumber from account where accountId=524526 and accountPhone='5653663251'
Note that, unlike the first query, this does not guarantee that only one row will be returned. Depending on your data, this could give any number of row, 0 included. You might need additional casting to align the datatypes.
You could do a FULL OUTER JOIN on the two tables and check for the count using CASE statement:
SELECT
CASE
WHEN COUNT(*) > 0
THEN 'TRUE'
ELSE 'FALSE'
END result,
FROM
customer c
FULL OUTER JOIN
account a
ON c.custPhone = a.accountPhone
WHERE c.customerId=3425632456
AND a.accountId=524526
AND c.custPhone='5653663251;
Try this
select
custId,
accountnumber
from customer c
left join account a
on c.custPhone = a.accountPhone
where customerId = 3425632456
;

Redshift - Finding number of times a flag appears for a particular ID

I have some sales data that shows if a bill has been generated for a customer. The column labelled bill_generated returns 'Y' if a bill has been generated else its blank. I am trying to find the list of customers for whom atleast one bill has been generated. There could be multiple rows for each cust_id as shown below:
cust_id, bill_generated
001,NULL
001,Y
002,NULL
002,NULL
003,Y
Could anyone advice on this. I am using Redshift DB. Thanks..
Try below using group by and having cluse
select cust_id from tablename
group by cust_id
having sum(case when bill_generated is null then 0 else 1 end)=1
you can use co-related sub-query
select * from t
where exists (select 1 from t t1
where t1.bill_generated='Y' and t1.cust_id=t.cust_id
)

TSQL syntax to feed results into subquery

I'm after some help on how best to write a query that does the following. I think I need a subquery but I don't know how to use the data returned in the row to feed back into the subquery without hardcoding values? A subquery may not be the right thing here?
Ideally I only want 1 variable ...WHERE t_Date = '2018-01-01'
Desired Output:
The COUNT Criteria column has the following rules
Date < current row
Area = current row
Name = current row
Value = 1
For example, the first row indicates there are 2 records with Date < '2018-01-01' AND Area = 'Area6' AND Name = 'Name1' AND Value = 1
Example Data:
SQLFiddle: http://sqlfiddle.com/#!18/92ba3/4
Effectively I only want to return the first 2 rows but summarise the historic data into a column based on the output in that column.
The right way to do this is to use the cumulative sum functionality in ANSI SQL and SQL Server since 2012:
select t.*,
sum(case when t.value = 1 then 1 else 0 end) over (partition by t_area, t_name order by t_date)
from t;
This actually includes the current row. If you have only one row per date (for the area/name combo), then you can just subtract it or use a windowing clause:
select t.*,
sum(case when t.value = 1 then 1 else 0 end) over
(partition by t_area, t_name
order by t_date
rows between unbounded preceding and 1 preceding
)
from t;
Use a self join to find records in the same table that are related to a particular record:
SELECT t1.t_Date, t1.t_Area, t1.t_Name, t1.t_Value,
COUNT(t2.t_Name) AS COUNTCriteria
FROM Table1 as t1
LEFT OUTER JOIN Table1 as t2
ON t1.t_Area=t2.t_Area
AND t1.t_Name=t2.T_Name
AND t2.t_Date<t1.t_Date
AND t2.t_Value=1
GROUP BY t1.t_Date, t1.t_Area, t1.t_Name, t1.t_Value

Determine active rows from multiple tables and place in a Variable Table

I have to determine how many rows are active from each Table. Then return the answers in one query AND put the results in a Table Variable.
a. Path
b. Course
c. Section
d. Event
I was able to determine the active rows with the following query:
SELECT * FROM [dbo].[ADF_Path]
WHERE PathActive is NULL
SELECT * FROM [dbo].[ADF_Course]
WHERE CourseActive = '1'OR
CourseActive = 'y'
SELECT * FROM [dbo].[ADF_Event]
WHERE EventActive = 'y'
Is it POSSIBLE to join these tables in order to arrive at the same conclusion
OR
How do I determine the active rows in 1 query?
Placing the query in a Variable Table is not a problem. I just need to know
how to formulate the query. (See Tables below)
Thank You
do you want something like?:
SELECT count(*) as cnt FROM [dbo].[ADF_Path] WHERE PathActive is NULL
union all
SELECT count(*) FROM [dbo].[ADF_Course] WHERE CourseActive = '1' OR CourseActive = 'y'
union all
SELECT count(*) FROM [dbo].[ADF_Event] WHERE EventActive = 'y'
you can also add column to distinguish between different counts, or summarize them like:
select sum(cnt) from ( <union query from above> ) as t