how to remove records when orderid is repeated - sql

OrderId InvoiceNumber LocationId
1 A1 1
1 B1 2
1 0
2 0
3 C1 2
3 0
Expected Output
OrderId InvoiceNumber LocationId
1 A1 1
1 B1 2
2 0
3 C1 2
In above Result....i want to remove those recored which have InvoiceNumber is null and LocationId is 0 when orderId is repeated in query.
In above Example....OrderId=1 record is repeated so then check InvoiceNuber is null and LocationId is 0 if found then removed it
OrderId=2 is not repeated so keep the record....
I tried this
Select * from tblName where isnull(InvoiceNuber,'')='' and LocationId=0
But...this query is wrong...
Thank uuu...!!..

You can use window functions:
select *
from (
select t.*, count(InvoiceNumber) over(partition by orderId) cnt
from mytable t
) t
where not (InvoiceNumber is null and locationId = 0 and cnt > 0)
This evicts rows where InvoiceNumber is null and locationId is 0 for which another row exists with the same orderId and a non-null InvoiceNumber.

Related

Update a column if a row is not a duplicate, or a row's ID isn't a certain number in SQL SSMS

I have a table, and I would like the following update command to set isExcluded = 1 to all rows where PhoneID and PhoneName are not duplicates and all rows where the ID doesn't not have the smallest number from a selected PhoneID if those rows do not have a duplicate PhoneID and PhoneName (i.e.: since all rows with PhoneID = 2 are not duplicates, the row containing PhoneName = b has the smallest ID, since it's ID = 3. Therefore, all rows with PhoneID = 2 and ID > 3 will have their IsExcluded set to 1).
ID
PhoneID
PhoneName
isExcluded
1
1
a
0
2
1
a
0
3
2
b
0
4
2
c
0
5
2
d
0
6
2
e
0
7
3
c
0
8
3
c
0
9
3
d
0
10
3
d
0
Here's my SQL script that I wrote. It only seems to get the non-duplicates only.
WITH Duplicates AS
(
SELECT
ID, PhoneID, PhoneName, isExcluded,
(ROW_NUMBER() OVER (PARTITION BY PhoneName, PhoneID ORDER BY ID)) AS RowNum
FROM
Phones
)
UPDATE Phones
SET isExcluded = 1
FROM Duplicates d
WHERE (
d.PhoneID = Phones.PhoneID
AND d.PhoneName = Phones.PhoneName
AND d.RowNum =< 1);
SELECT * FROM Phones;
This table should be the result of my command.
ID
PhoneID
PhoneName
isExcluded
1
1
a
0
2
1
a
0
3
2
b
0
4
2
c
1
5
2
d
1
6
2
e
1
7
3
c
0
8
3
c
0
9
3
d
1
10
3
d
1
This looks to be a variation of a gaps and islands problem, which you can solve by first grouping the partitions and then using an updatable CTE to assign the isExcluded value
with gp as (
select *,
Row_Number() over(order by id)
- Row_Number() over(partition by phoneid, phonename order by id) gp
from t
), p as (
select *,
case when Min(gp) over(partition by phoneid) <gp then 1 end IsEx
from gp
)
update p set isExcluded = isEx
where IsEx = 1
See working DB<>Fiddle

How can I create a new table by deleted duplicated rows in SQL?

I have a table which looks like this
ID A B C
1 1 0 0
1 1 0 0
2 1 1 0
2 1 1 0
How can I remove the duplicated rows in SQL so that I am left with a table that looks like this:
ID A B C
1 1 0 0
2 1 1 0
use row_number()
with cte as
(
select *, row_number() over(partition by id order by id) as rn
from tablename
)
delete from cte where rn<>1
select distinct * from <table_name>
This is the simplest way.

sql where have all multiple conditions in entry table

I've been trying to wrap my brain around this using joins, subquery joins, not exists clauses and I keep failing to come up with a query that produces the correct results.
I have 2 table's Trans and TransEntry
Trans Table (PRIMARY TransID)
TransID | Date
-----------
1 1/1/18
2 1/2/18
3 1/3/18
TransEntry Table (PRIMARY TransEntryID)
TransEntryID | TransID |Item
-----------
1 1 A
2 1 B
3 1 C
4 2 A
5 2 D
6 2 F
7 3 A
8 3 B
9 3 G
10 3 C
I need to have all TransID from TransEntry where the have item A and item C in the Entry, in our sample it will be only TransID (1,3)
or
SELECT TransID FROM TransEntry WHERE Item = 'A'
INTERSECT
SELECT TransID FROM TransEntry WHERE Item = 'C'
I think something like this should work:
SELECT TransID
FROM TransEntry
WHERE Item in ('A','C')
GROUP BY TransID
HAVING Count(DISTINCT Item) = 2;
Here's a sqlfiddle showing this
CREATE TABLE TransEntry(
TransEntryID INTEGER NOT NULL PRIMARY KEY
,TransID INTEGER NOT NULL
,Item VARCHAR(1) NOT NULL
);
INSERT INTO TransEntry(TransEntryID,TransID,Item) VALUES
(1,1,'A')
,(2,1,'B')
,(3,1,'C')
,(4,2,'A')
,(5,2,'D')
,(6,2,'F')
,(7,3,'A')
,(8,3,'B')
,(9,3,'G')
,(10,3,'C');
SELECT TransID
FROM TransEntry
WHERE Item in ('A','C')
GROUP BY TransID
HAVING Count(DISTINCT Item) = 2
+---------+
| TransID |
+---------+
| 1 |
| 3 |
+---------+
My answer wasn't as succinct as Aaron's, but in case it's helpful:
SELECT
TransID
FROM
Trans
WHERE
TransID IN ( SELECT TransID FROM TransEntry WHERE Item = 'A' ) AND
TransID IN ( SELECT TransID FROM TransEntry WHERE Item = 'C' )
you can go for something like this:
select transId
from
(
select
TransID ,
case when item = 'A' then 1 else 0 end as HasA,
case when item = 'C' then 1 else 0 end as HasC
from TransEntry
) a
group by transId
having sum(hasA) > 0 and sum(hasC) > 0
You can use GROUP BY :
SELECT TransID
FROM TransEntry
GROUP BY TransID
HAVING SUM(CASE WHEN item = 'A' THEN 1 ELSE 0 END) > 0 AND
SUM(CASE WHEN item = 'C' THEN 1 ELSE 0 END) > 0;
SELECT TransEntry.TransID, TransEntry.Item, GROUP_CONCAT(TransEntry.Item) AS items
FROM TransEntry
group by TransEntry.TransID Having Find_In_Set('A',items)>0 and Find_In_Set('C',items)>0
see the jsfiddle

different conditions on different groups

I have a table like this. I would like to get the first row grouped by id where acc1 is not null and if all the rows in the acc1 are null then i would want to get all the rows.
id acc1 acc2
1 null 1
1 1 1
1 1 2
1 2 2
2 null 1
2 null 2
2 null 3
2 null 4
I would like to get an output like this:
id acc1 acc2
1 1 1
2 null 1
2 null 2
2 null 3
2 null 4
Assuming acc1 is unique when not null (for each id):
select t.*
from (select t.*,
rank() over (partition by id
order by (case when acc1 is null then 2 else 1 end), acct1
) as seqnum
from t
) t
where seqnum = 1;
If it is not unique, this just requires a little more work:
select t.*
from (select t.*,
row_number() over (partition by id
order by acct1, acct2
) as seqnum,
count(acct1) over (partition by id) as cnt
from t
) t
where seqnum = 1 or cnt = 0;
This assumes that "first" is based on acct1, acct2. SQL tables are inherently unordered, so you need a column that specifies the ordering.
SELECT *
FROM mytable
QUALIFY Max(acc1) Over (PARTITION BY id) IS NULL -- only NULLs
OR Row_Number() Over (PARTITION BY id -- or the first non-null value
ORDER BY acc1 NULLS LAST) = 1

Grouping in SELECT statement with two columns that contain different values among rows

I have a SQL query I am performing against some tables SQL Server database. The result set looks something like this:
Column1 | Column2 | Column3 | InvoiceNumber | InvoiceID
-------------------------------------------------------
1 1 1 1234 1
1 1 1 5678 2
I only want to get back the row with the smallest InvoiceID and its corresponding InvoiceNumber.
I apply min(InvoiceID) in the SELECT statement. In the GROUP BY clause, I am grouping by every column except InvoiceNumber and InvoiceID. I am getting an error since InvoiceNumber isn't contained in an aggregate function in the SELECT statement and isn't present in the GROUP BY clause.
How do I structure the query so I only get back the row with the smallest InvoiceID and the corresponding InvoiceNumber?
Edit
Here is some additional information:
The result set is actually going to contain many rows. It's only occassionally that multiple rows will have the same values for Column1, Column2, and Column3, but different values for the InvoiceNumber and InvoiceID. So a better example of the result set would look like this:
Column1 | Column2 | Column3 | InvoiceNumber | InvoiceID
-------------------------------------------------------
1 1 1 1234 1
1 1 1 5678 2
2 1 1 1287 3
2 1 2 1287 3
2 2 1 1287 3
3 1 1 5555 4
3 1 2 5555 4
So when Column1, Column2, and Column3 are the same, I only want the result with the smallest InvoiceID, and whatever the InvoiceNumber was for the row with the smallest InvoiceID. Here's what I want it to actually look like in this case:
Column1 | Column2 | Column3 | InvoiceNumber | InvoiceID
-------------------------------------------------------
1 1 1 1234 1
2 1 1 1287 3
2 1 2 1287 3
2 2 1 1287 3
3 1 1 5555 4
3 1 2 5555 4
Only the second row was removed because it had a smaller InvoiceID and was the only row that had the same values for Column1, Column2, and Column3 as a different row.
Here's what my SQL query currently looks like:
SELECT c.CollectionID
, p.Account
, d.TransactionID
, id.InvoiceNumber
, i.InvoiceID
FROM collection c
INNER JOIN documents d on c.GlobalCollectionID = d.GlobalCollectionID
LEFT JOIN payment p on c.GlobalCollectionID = p.GlobalCollectionID
AND d.TransactionID = p.TransactionID
LEFT JOIN invoice i on c.GlobalCollectionID = i.GlobalCollectionID
AND d.TransactionID = i.TransactionID
LEFT JOIN invoicedata id on i.InvoiceID = id.InvoiceID
WHERE c.ProcessDate = '2013-11-29'
AND c.Item = 11805123
AND c.CollectionID in ('1104', '1105', '1106')
ORDER BY c.CollectionID
, d.TransactionID
, i.InvoiceID
, p.Account
It would probably be easier to help if you'd posted the SQL to your initial query.
You probably want to move your MIN() function into a WHERE clause:
SELECT Column1 ,Column2 ,Column3 ,InvoiceNumber , InvoiceID
FROM Table_Name
WHERE InvoiceID = (SELECT MIN(InvoiceID) FROM Table_Name)
Now you have provided some data and have changed your requirement as well anyway with this new data and new requirement , try this
DECLARE #T Table (Column1 INT,Column2 INT,Column3 INT,InvoiceNumber INT, InvoiceID INT)
INSERT INTO #T
VALUES
(1,1,1,1234,1),
(1,1,1,5678,2),
(2,1,1,1287,3),
(2,1,2,1287,3),
(2,2,1,1287,3),
(3,1,1,5555,4),
(3,1,2,5555,4)
;WITH CTE
AS
(
SELECT Column1 ,Column2
,Column3 ,InvoiceNumber , InvoiceID
, rn = ROW_NUMBER() OVER (PARTITION BY Column1 ,Column2 ,Column3 ORDER BY InvoiceID ASC)
FROM #T
)
SELECT * FROM CTE
WHERE rn = 1
Result Set
Column1 Column2 Column3 InvoiceNumber InvoiceID rn
1 1 1 1234 1 1
2 1 1 1287 3 1
2 1 2 1287 3 1
2 2 1 1287 3 1
3 1 1 5555 4 1
3 1 2 5555 4 1
Your Query
;WITH CTE
AS
(
SELECT YourQuery.*
, rn = ROW_NUMBER() OVER (PARTITION BY c.CollectionID , p.Account , d.TransactionID ORDER BY InvoiceID ASC)
(
SELECT c.CollectionID
, p.Account
, d.TransactionID
, id.InvoiceNumber
, i.InvoiceID
FROM collection c
INNER JOIN documents d on c.GlobalCollectionID = d.GlobalCollectionID
LEFT JOIN payment p on c.GlobalCollectionID = p.GlobalCollectionID
AND d.TransactionID = p.TransactionID
LEFT JOIN invoice i on c.GlobalCollectionID = i.GlobalCollectionID
AND d.TransactionID = i.TransactionID
LEFT JOIN invoicedata id on i.InvoiceID = id.InvoiceID
WHERE c.ProcessDate = '2013-11-29'
AND c.Item = 11805123
AND c.CollectionID in ('1104', '1105', '1106')
)YourQuery
)
SELECT C.CollectionID , C.Account , C.TransactionID,C.InvoiceNumber, C.InvoiceID
FROM CTE C
WHERE rn = 1
This is the query you're looking for:
SELECT Column1, Column2, Column3, InvoiceNumber, InvoiceID
FROM (
SELECT *,
rn = ROW_NUMBER() OVER (PARTITION BY Column1, Column2, Column3
ORDER BY InvoiceID ASC)
FROM example
) e
WHERE rn = 1
See it working on SQLFiddle. Just swap in your query for the nested query, but keep the ROW_NUMBER field.
Produces the correct result set:
COLUMN1 COLUMN2 COLUMN3 INVOICENUMBER INVOICEID
----------------------------------------------------
1 1 1 1234 1
2 1 1 1287 3
2 1 2 1287 3
2 2 1 1287 3
3 1 1 5555 4
3 1 2 5555 4