I have a table in SQL Server, in this table I have a column chq_no_start with some duplicate cheque no, but the account id is different according those cheque no.
Now I want to show only one cheque no from those duplicate cheque no, no matter if one account id is missing.
I show my output:
Try this...
Select
distinct chq_no_start,
(select top 1 alt_acc_id from Table_name where chq_no_start= tn.chq_no_start order by alt_acc_id) Account_ID
From
Table_name tn
Order by
chq_no_start
Try using the DISTINCT keyword before the column name.
You could try the following:
with cte as (
select alt_acc_id, issue_date, no_of_chq, chq_no_start,
row_number() over (partition by chq_no_start order by alt_acc_id) RowNum
from your_table
where your_column = 'your_value')
select * from cte
where RowNum = 1
Related
I have a select query which returns a couple of rows grouped by ParentId. How can I add a new row with sum of a column after each parentId group?
For now I have kept the data in a temp table and the result is as below.
And I want to add a new row at the end of each ParentId group as below with the sum of column LoanAmount.
Any help will be appreciated. Many thanks.
You can use a common table expression to achieve this. Here I've created a cte with rank column for getting it sorted in order.
;WITH cte AS
(SELECT ParentId,
sum(LoanAmount) LoanAmount,
max(rank) + 1 AS rank
FROM test
GROUP BY ParentId)
SELECT *
FROM test
UNION ALL
SELECT *
FROM cte
ORDER BY ParentId, rank
rextester
See this link here enter link description here
I think you want:
SELECT ParentID, SUM(VALUE1), SUM(VALUE2)
FROM tableName
GROUP BY ID
You cant do it after each group or at the bottom like in excel, but you create a 'new table' in your query effectively.
Yeah having seen your updated comment, you main issue is youre thinking of it like excel, SQL is not a spreadsheet tool - its a relational database. Id suggest going through a SQL intro - youll pick up the concepts quite fast.
The query I gave you could be created as a stored procedure.
If you feel I've answered your question, id appreciate an upvote :)
You can make sum of group by subquery then combine them in union
; with cte as
( select 9999 as Slno, Level, ParentId, Ent_id, relation, sum(colname) as colname from table group by Level, ParentId, Ent_id, relation)
, ct as ( select row_number() over (partition by ParentId order by level) as Slno, Level, ParentId, Ent_id, Name, --- rest of your column names
colname from table
union all
select Slno, Level, ParentId, Ent_id, '' as Name, ---rest of '' for each column with column name as alias
colname from cte )
select Slno, Level, ParentId, Ent_Id, Name, ---- your columns of table
colname from ct order by Slno
This is just rough idea. Feel free to ask for any confusion.
Post your exact schema for accurate details.
I am trying to get available balance on last(max) date. I am trying to write below query but it is showing error.
select ACCOUNT_ID,AVAIL_BALANCE,OPEN_DATE,MAX(LAST_ACTIVITY_DATE)
from ACCOUNT
group by CUST_ID;
Column 'ACCOUNT.ACCOUNT_ID' is invalid in the select list because it
is not contained in either an aggregate function or the GROUP BY
clause.
I am new to sql. Can anyone let me know where I am wrong in this query?
Any column not having a calculation/function on it must be in the GROUP BY clause.
select ACCOUNT_ID,AVAIL_BALANCE,OPEN_DATE,MAX(LAST_ACTIVITY_DATE)
from ACCOUNT
group by ACCOUNT_ID,AVAIL_BALANCE,OPEN_DATE;
If you're wanting the most recent row for each customer, think ROW_NUMBER(), not GROUP BY:
;With Numbered as (
select *,ROW_NUMBER() OVER (
PARTITION BY CUST_ID
ORDER BY LAST_ACTIVITY_DATE desc) rn
from Account
)
select ACCOUNT_ID,AVAIL_BALANCE,OPEN_DATE,LAST_ACTIVITY_DATE
from Numbered
where rn=1
I think you want to select one records having max(LAST_ACTIVITY_DATE) for each CUST_ID.
For this you can use TOP 1 WITH TIES like following.
SELECT TOP 1 WITH TIES account_id,
avail_balance,
open_date,
last_activity_date
FROM account
ORDER BY Row_number()
OVER (
partition BY cust_id
ORDER BY last_activity_date DESC)
Issue with your query is, you can't select non aggregated column in select if you don't specify those columns in group by
If you want to get the max activity date for a customer then your query should be as below
select CUST_ID, MAX(LAST_ACTIVITY_DATE)
from ACCOUNT
group by CUST_ID;
You can't select any other column which is not in the group by clause. The error message also giving the same message.
with query(CUST_ID, LAST_ACTIVITY_DATE) as
(
select
CUST_ID,
MAX(LAST_ACTIVITY_DATE) as LAST_ACTIVITY_DATE
from ACCOUNT
group by CUST_ID
)
select
a.ACCOUNT_ID,
a.AVAIL_BALANCE,
a.OPEN_DATE,
a.LAST_ACTIVITY_DATE
from ACCOUNT as a
inner join query as q
on a.CUST_ID = q.CUST_ID
and a.LAST_ACTIVITY_DATE = q.LAST_ACTIVITY_DATE
I'm new to SQL in general and I need to delete all duplicates in a given database.
For the moment, I use this DB to experiment some things.
The table currently looks like this :
I know I can find all duplicates using this query :
SELECT COUNT(*) AS NBR_DOUBLES, Name, Owner
FROM dbo.animals
GROUP BY Name, Owner
HAVING COUNT(*) > 1
but I have a lot of trouble finding an adapted and updated solution to not only find all the duplicates, but also delete them all, only leaving one of each.
Thanks a lot for taking some of your time to help me.
;WITH numbered AS (
SELECT ROW_NUMBER() OVER(PARTITION BY Name, Owner ORDER BY Name, Owner) AS _dupe_num
FROM dbo.Animals
)
DELETE FROM numbered WHERE _dupe_num > 1;
This will delete all but one of each occurance with the same Name & Owner, if you need it to be more specific you should extend the PARTITION BY clause. If you want it to take in account the entire record you should add all your fields.
The record left behind is currently random, since it seems you do not have any field to have any sort of ordering on.
What you want to do is use a projection that numbers each record within a given duplicate set. You can do that with a Windowing Function, like this:
SELECT Name, Owner
,Row_Number() OVER ( PARTITION BY Name, Owner ORDER BY Name, Owner, Birth) AS RowNum
FROM dbo.animals
ORDER BY Name, Owner
This should give you results like this:
Name Owner RowNum
Ecstasy Sacha 1
Ecstasy Sacha 2
Ecstasy Sacha 3
Gremlin Max 1
Gremlin Max 2
Gremlin Max 3
Outch Max 1
Outch Max 2
Outch Max 3
Now you want to convert this to a DELETE statement that has a WHERE clause targeting rows with RowNum > 1. The way to use a windowing function with a DELETE is to first include the windowing function as part of a common table expression (CTE), like this:
WITH dupes AS
(
SELECT Name, Owner,
Row_Number() OVER ( PARTITION BY Name, Owner ORDER BY Name, Owner, Birth) AS RowNum
FROM dbo.animals
)
DELETE FROM dupes WHERE RowNum > 1;
This will delete later duplicates, but leave row #1 for each group intact. The only trick now is to make sure row #1 is the correct row, since not all of your duplicates have the same values for the Birth or Death columns. This is the reason I included the Birth column in the windowing function, while other answers (so far) have not. You need to decide if you want to keep the oldest animal or the youngest, and optionally change the Birth order in the OVER clause to match your needs.
Use CTE. I will show you a sample :
Create table #Table1(Field1 varchar(100));
Insert into #Table1 values
('a'),('b'),('f'),('g'),('a'),('b');
Select * from #Table1;
WITH CTE AS(
SELECT Field1,
RN = ROW_NUMBER()OVER(PARTITION BY Field1 ORDER BY Field1)
FROM #Table1
)
--SELECT * FROM CTE WHERE RN > 1
DELETE FROM CTE WHERE RN > 1
What I am doing is, numbering the rows. If there are duplicates based on PARTITION BY columns, it will be numbered sequentially, else 1.
Then delete those records whose count is greater than 1.
I won't spoon feed you solution hence you will have to play with PARTITION BY to reach your output
output :
Select * from #Table1;
Field1
---------
a
b
f
g
a
b
/*with cte as (...) SELECT * FROM CTE;*/
Field1 RN
------- -----
a 1
a 2
b 1
b 2
f 1
g 1
if NBR_DOUBLES had an ID field, I believe you could use this;
DELETE FROM NBR_DOUBLES WHERE ID IN
(
SELECT MAX(ID)
FROM dbo.animals
GROUP BY Name, Owner
HAVING COUNT(*) > 1
)
I have to write an SELECT INTO T-SQL script for a table which has columns acc_number, history_number and note.
How do i facilitate an incremental value of history_number for each record being inserted via SELECT INTO.
Note, that the value for history_number comes off as a different value for each account from a different table.
SELECT history_number = IDENTITY(INT,1,1),
... etc...
INTO NewTable
FROM ExistingTable
WHERE ...
You could use ROW_NUMBER instead of identity i.e. ROW_NUMBER() OVER (ORDER BY )
SELECT acc_number
,o.historynumber
,note
,o.historynumber+DENSE_RANK() OVER (Partition By acc_number ORDER BY Note) AS NewHistoryNumber
--Or some other order by probably a timestamp...
FROM Table t
INNER JOIN OtherTable o
ON ....
Working Fiddle
The will give you an incremented count starting from history number for each accnum. I suggest you use a better order by in the rank but there was not enough info in the question.
This answer to this question may help you as well
Question
Suppose your SELECT statement is like this
SELECT acc_number,
history_number,
note
FROM [Table]
Try this Query as below.
SELECT ROW_NUMBER() OVER (ORDER BY acc_number) ID,
acc_number,
history_number,
note
INTO [NewTable]
FROM [Table]
I have a table with the following example format:
ID Name
1 NULL
1 NULL
2 HELLO
3 NULL
3 BYE
My goal is to remove repeated lines with same IDS, but with restrictions.
According to the example, I need to remove a row with ID-1, and the row with ID-3 and with no value (NULL).
I would stick with the table:
ID Name
1 NULL
2 HELLO
3 BYE
How can I do this in sql server? thank you
To just select the data, you can use a simple CTE (common table expression);
WITH cte AS (
SELECT id, name,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY name DESC) rn
FROM myTable
)
SELECT id,name FROM cte WHERE rn=1;
An SQLfiddle to test with.
If you mean to delete the duplicates from the table and not just select the data without updating anything, you could use the same CTE;
WITH cte AS (
SELECT id, name,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY name DESC) rn
FROM myTable
)
DELETE FROM cte WHERE rn<>1;
Another SQLfiddle to test with, and remember to always back up your data before running destructive SQL statements from random people on the Internet.