Sybase + how to compute sequence number for a speicific group - sybase

Date column1 column2 column3 column4 column5
01-Jan-17 A AB 10 AB_1 10
02-Jan-17 B AB 20 AB_2 10
03-Jan-17 C AB 30 AB_3 10
04-Jan-17 D AB 20 AB_4 -10
05-Jan-17 E AB 40 AB_5 20
06-Jan-17 X GH 30 GH_1 30
07-Jan-17 V GH 40 GH_2 10
08-Jan-17 A GH 50 GH_3 10
Requirement1 :For all the columns having same value in column2, the column4 should be numbered sequentially
Requirement2:For all the columns having same value in column2, the column5 should be computed as current value of column3 - previous value of column3
Appreciate your help!!
I'm using Adaptive Server Enterprise/15.7/EBF 22234 SMP SP121 /P/x86_64/Enterprise Linux/ase157sp12x/3660/64-bit/FBO/

You can achieve this with multi-step processing as follows (I didn;t test it, but you'll get the idea). Assuming your table is named 't'.
select your_date, column1, column2, column3, id = identity(9) into #t1 from t order by column2, column3 -- this seems to be the ordering you want?
select column2, min(id) as min_id into #t2 from #t1 group by column2
select #t1.* column4 = (#t1.id - #t2.min_id + 1) into #t3 from #t1, #t2 where #t2.column2 = #t1.column2
select ta.*, column5 = case when tb.id is null or tb.column2 <> ta.column2 then ta.column3 else ta.column3 - tb.column3 from #t3 ta, #t1 tb where ta.id *= (tb.id - 1)

Related

SSMS / TSQL - Insert multiple records for every record found in query

I want to insert multiple records (two to be specific) with a unique ID for Column 1 (in both records created) for every record that matches a specific query criteria . The rest of the values for the insert should be pulled from the respective columns on the query. In the first insert Column2 will be the original value from Column1, and on the second insert Column2 will be the original value from Column2.
Ideally, what I'm after is:
FIND RECORDS THAT MEETS CRITERIA
FOR EACH RECORD
GENERATE GUID
INSERT TWO NEW RECORDS WITH GUID AS COLUMN1, AND REMAINING COULMNS FROM
CURRENT RECORD FOUND
RECORDS
123 abc 3 4 5
456 def 6 7 8
RECORD 1
123 abc 3 4 5
NEW RECORDS AFTER INSERTS
UID1 123 3 4 5
UID1 abc 3 4 5
ROW 2
456 def 6 7 8
NEW RECORDS AFTER INSERTS
UID2 456 6 7 8
UID2 def 6 7 8
The below INSERT SELECT FROM handles exactly what I want to do but only for a single insert per record found.
INSERT INTO table1
(
Column1,
Column2,
Column3
Column4
Column5
)
SELECT
NEWID(), -- unique ID
Column2, -- or Column1 based on which insert we are doing
Column3, -- always column 3
Column4, --always column 4
Column5 -- always column 5
FROM
table1
WHERE Column1 IS NOT NULL
AND Column1 != Column4
Is there an easy way to do this via TSQL? I need it to run in bulk, for a potential of thousands of records meeting the query conditions.
WITH xQ(UUID,Column2,Column3,Column4,Column5) AS
(
SELECT
NEWID(),
Column1,
Column2,
Column3,
Column4,
Column5
FROM
table1
WHERE Column1 IS NOT NULL
AND Column1 != Column4
)
INSERT INTO table1
(
Column1,
Column2,
Column3,
Column4,
Column5
)
SELECT
UUId,
Column1,
Column3,
Column4,
Column5
FROM xQ
UNION
SELECT
UUId,
Column2,
Column3,
Column4,
Column5
FROM xQ
Here's a possibility. First use your query that generates the first set of rows and insert them into a temp table.
Rextester Demo
SELECT
NEWID() AS [uid], -- unique ID
column1,
Column2, -- or Column1 based on which insert we are doing
Column3, -- always column 3
Column4, --always column 4
Column5 -- always column 5
INTO #temp
FROM
table1
WHERE Column1 IS NOT NULL
AND Column1 != Column4
Now using that temp table we can do a UNION with the same table to generate the second set of rows and insert them into table1.
INSERT INTO table1
SELECT
[uid] AS Column1
, CAST(column1 AS NVARCHAR(3)) AS Column2
, column3
, column4
, column5
FROM #temp
UNION ALL
SELECT
[uid] AS Column1
, column2
, column3
, column4
, column5
FROM #temp
ORDER BY Column1
DROP TABLE #temp

SQL Server order by case

I want to create a fourth column with this query:
select * from (select ID, column0, column1, column2, column3 = Case when
column2 = '' then column1 else column2 end, row_number() over(partition by
column0 order by [column3]) as column4 from myTable) ti
But this error appears:
Invalid column name 'column3'.
I want this result: (red marked column):
you need to use order by from outside of subquery as below:
Select *, row_number() over(partition by
column3 order by [Id]) as column4
from (select ID, column0, column1, column2, column3 = Case when
column2 = '' then column1 else column2 end
from myTable) ti
For your 4th column in image you need to partition by column3 order by id. If you do Partition by column0 then you will get all 1's
This way it will work:
select *, row_number() over(partition by
column0 order by [column3]) as column4 from
(select ID, column0, column1, column2, column3 = Case when
column2 = '' then column1 else column2 end from myTable) ti

Removing rows , if they have duplicate

Lets suppose I have a following table in sql server 2008.
Column1 Column2 Column3
1 2 1
1 2 1
5 1 1
3 2 1
3 2 1
4 1 1
The output should be following
Column1 Column2 Column3
5 1 1
4 1 1
If a row has a duplicates present then , the original row and all the duplicate rows are to be deleted.If a row doesnot have any duplicates. Then it is kept. How can i achieve this?
Try like this,
DECLARE #Table TABLE (
Column1 INT
,Column2 INT
,Column3 INT
)
INSERT INTO #Table
(Column1,Column2,Column3)
VALUES
(1,2,1),
(1,2,1),
(5,1,1),
(3,2,1),
(3,2,1),
(4,1,1)
SELECT *
FROM #Table
DELETE t1
FROM #Table t1
INNER JOIN (
SELECT Column1
,Column2
,Column3
FROM #Table t
GROUP BY Column1
,Column2
,Column3
HAVING count(*) > 1
) t2 ON t1.column1 = t2.Column1
AND t1.column2 = t2.column2
AND t1.column3 = t2.column3
SELECT * FROM #Table

SQL Server distinct rows count

Say there is the following table in SQL Server :
ID Column1 Column2 Column3
1 1 2 10
1 1 2 20
2 1 2 30
2 1 2 40
3 3 4 50
3 3 4 60
3 3 4 70
I need to select the SUM on Column3 grouped by Column1, Column2 and select the count of rows with DISTINCT "ID". Consider the query :
SELECT SUM(Column3) AS Column3
COUNT(*) AS Count
FROM MyTable
GROUP BY Column1,
Column2
The result will be :
Column3 Count
100 4
110 3
I expect to get :
Column3 Count
100 2
110 1
So the count here will be by DISTINCT "ID" values.
In the first row 2 means there are two different ID values (1 and 2) with the same Column1, Column2
In the second row 1 means there is just one distinct value (that is 3) with the same Column1, Column2.
Can you please advice me the correct way to get the expected result.
Thanks in advance.
Use COUNT(DISTINCT): http://msdn.microsoft.com/en-us/library/ms175997.aspx
SELECT SUM(Column3) AS Column3
COUNT(DISTINCT ID) AS Count
FROM MyTable
GROUP BY Column1,
Column2
Not sure I'm understanding you right, but does this work?:
;WITH cte AS (SELECT ID, column1, column2, SUM(column3) AS column3sum FROM table GROUP BY id, column1, column2)
SELECT SUM(column3sum), COUNT(ID)
FROM cte
GROUP BY column1, column2

choosing row (from group) with max value in a SQL Server Database

I have a large database and am putting together a report of the data. I have aggregated and summed the data from many tables to get two tables that look like the following.
id | code | value id | code | value
13 | AA | 0.5 13 | AC | 2.0
13 | AB | 1.0 14 | AB | 1.5
14 | AA | 2.0 13 | AA | 0.5
15 | AB | 0.5 15 | AB | 3.0
15 | AD | 1.5 15 | AA | 1.0
I need to get a list of id's, with the code (sumed from both tables) with the largest value.
13 | AC
14 | AA
15 | AB
There are 4-6 thousand records and it is not possible to change the original tables. I'm not too worried about performance as I only need to run it a few times a year.
edit:
Let me see if I can explain a bit more clearly, imagine the id is the customer id, the code is who they ordered from and the value is how much they spent there.
I need a list of the all the customer id's and the store that customer spent the most money at (and if they spent the same at two different stores, put a value such as 'ZZ' in for the store name).
try this:
DECLARE #Table1 table (id int, code char(2), value decimal(5,1))
INSERT #Table1 VALUES (13 , 'AA' , 0.5)
INSERT #Table1 VALUES (13 , 'AB' , 1.0)
INSERT #Table1 VALUES (14 , 'AA' , 2.0)
INSERT #Table1 VALUES (15 , 'AB' , 0.5)
INSERT #Table1 VALUES (15 , 'AD' , 1.5)
DECLARE #Table2 table (id int, code char(2), value decimal(5,1))
INSERT #Table2 VALUES (13 , 'AC' , 2.0)
INSERT #Table2 VALUES (14 , 'AB' , 1.5)
INSERT #Table2 VALUES (13 , 'AA' , 0.5)
INSERT #Table2 VALUES (15 , 'AB' , 3.0)
INSERT #Table2 VALUES (15 , 'AA' , 1.0)
SELECT
dt.id, MAX(dt.code) AS code, sum(dt.value) as value
from (select id, code, value
from #Table1
UNION ALL
select
id, code, value
from #Table2
) dt
group by dt.id
order by id
OUTPUT:
id code value
----------- ---- ---------------------------------------
13 AC 4.0
14 AB 3.5
15 AD 6.0
(3 row(s) affected)
I'm not sure what you are after? this is the MAX code per id summing the value. if this is not what you are after please specify i nthe question more clearly
EDIT after OP's edit, using same tables as code from above:
;WITH AllTAbles AS
(select
id, code, value
from #Table1
UNION ALL
select
id, code, value
from #Table2
)
, MaxValues AS
(SELECT
dt.id, MAX(dt.value) as MaxValue, SUM(dt.value) AS SumValue
from AllTAbles dt
group by dt.id
)
, StoreCount AS
(SELECT
a.id,a.Code, COUNT(*) AS StoreCount
FROM AllTAbles a
INNER JOIN MaxValues m ON a.id=m.id AND a.value=m.MaxValue
GROUP BY a.id,a.Code
)
SELECT
s.id
,CASE
WHEN s.StoreCount=1 THEN s.Code
ELSE 'ZZ'
END AS code
,m.SumValue
FROM StoreCount s
INNER JOIN MaxValues m ON s.id=m.id
ORDER BY s.id
OUTPUT:
id code SumValue
----------- ---- ----------
13 AC 4.0
14 AA 3.5
15 AB 6.0
(3 row(s) affected)
OP doesn't say the version of SQL Server, so here is a pre SQL Server 2005 version that does not use CTEs, has same output as the CTE version above:
SELECT
s.id
,CASE
WHEN s.StoreCount=1 THEN s.Code
ELSE 'ZZ'
END AS code
,s.SumValue
FROM (SELECT
a.id,a.Code, COUNT(*) AS StoreCount, m.SumValue
FROM (select
id, code, value
from #Table1
UNION ALL
select
id, code, value
from #Table2
) a
INNER JOIN (SELECT
dt.id, MAX(dt.value) as MaxValue, SUM(dt.value) AS SumValue
from (select
id, code, value
from #Table1
UNION ALL
select
id, code, value
from #Table2
) dt
group by dt.id
) m ON a.id=m.id AND a.value=m.MaxValue
GROUP BY a.id,a.Code,m.SumValue
) s
ORDER BY s.id
select id, code, sum(value) as value
from
(
select id, code, value
from yyy
UNION
select id, code, value
from zzz
) aaa
group by id, code
order by sum(value)
or this removing id from the grouping:
select code, sum(value) as value
from
(
select id, code, value
from yyy
UNION
select id, code, value
from zzz
) aaa
group by code
order by sum(value)

Resources