Sybase ASE Transpose Indefinite Number of Rows to Columns - pivot-table

I have tried doing pivot tables but only for fixed number of rows.
I have the following records:
ID CODE
=== ====
1 AAA
1 BBB
1 CCC
2 DDD
3 EEE
3 FFF
4 GGG
4 HHH
4 III
4 JJJ
And my expected result is:
ID CODE1 CODE2 CODE3 CODE4
=== ===== ===== ===== =====
1 AAA BBB CCC
2 DDD
3 EEE FFF
4 GGG HHH III JJJ
Take note that the number of rows returned per id is not fixed. I want to avoid cursor as much as possible.

To do it without a loop, you need to adding an artificial row number, for example through an identity column. If you do not want to change your schema, copy the whole table into a temp table first.
(I didn't check for syntax errors but you'll get the idea)
alter table yourtab add seq int identity not null
select id, min_seq=min(seq) into #t from yourtab group by id
select id=max(id), code1=max(code1), code2=max(code2),
code3=max(code3), (etc) from ( select id = yourtab.id,
code1=case (yourtab.id-#t.min_seq) when 0 then code else null end,
code2=case (yourtab.id-#t.min_seq) when 1 then code else null end,
code3=case (yourtab.id-#t.min_seq) when 2 then code else null end,
[...etc...]
from yourtab, #t where yourtab.id = #t.id order by
yourtab.id ) as newtab

Related

How to aggregate several columns into a JSON file in HIVE and avoid nulls

user_id reservation_id nights price
--------------------------------------
AAA 10001 1 100
AAA 10002 1 120
BBB 20003 7 350
ccc 10005 150
DDD 10007 3
CCC 10006 5
to
user_id reservation_details
AAA [{"nights":"1", "price":"100"}, {"nights":"1","price":"120"}]
BBB [{"nights":"7", "price":"350"}]
CCC [{"price":"150"}, {"nights":"3"}]
DDD [{"nights":"5"}]
Here my query is
select user_id
,concat("
{",concat_ws(',',collect_list(concat(string(reservation_id),":
{'nights':",string(nights),",'price':",string(price),"}"))),"}") as
reservation_details
from mytable
group by user_id
I want to eliminate the columns which have value as nulls and convert that single quotes into double quotes which looks like a exact JSON.
Using in-built datatypes map and array along with a case expression to handle nulls.
select user_id,collect_list(map_nights_price)
from (select user_id,
case when nights is null then map('price',price)
when price is null then map('nights',nights)
else map('nights',nights,'price',price) end as map_nights_price
from mytable
where not (price is null and nights is null) --ignore row where price and nights are null
) t
group by user_id

SQL Server select join detect if common column between two tables are different

I am trying to write a function to check between two tables which have a common column with the same name and ID values.
Table 1: CompanyRecords
CompanyRecordsID CompanyId CompanyName CompanyProcessID
-----------------------------------------------------------
1 222 Sears 123
2 333 JCPenny 456
Table 2: JointCompanies
JointCompaniesID CompanyId CompanyName ComanyProcessID
-----------------------------------------------------------
3 222 KMart 123
4 444 Walmart 001
They both use the same foreign key CompanyProcessID with value 123.
How do I write a select statement when it is passed the CompanyProcessID to tell if the CompanyId has changed for the same CompanyProcessId.
I assume it is a join between the two tables with WHERE CompanyProcessID
Thanks for any help.
Is this what you want?
select max(case when cr.name = jc.name then 0 else 1 end) as name_not_same
from CompanyRecords cr join
JointCompanies jc
on cr.ComanyProcessID = jc.ComanyProcessID
where cr.ComanyProcessID = ?

Transitive Group Query on 2 Columns in SQL Server

I need help with a transitive query in SQL Server.
I have a table with [ID] and [GRPID].
I would like to update a third column [NEWGRPID] based on the following logic:
For each [ID], get its GRPID;
Get all of the IDs associated with the GRPID from (1);
Set [NEWGRPID] equal to an integer (variable that is incremented by 1), for all of the rows from step (2)
The idea is several of these IDs are "transitively" linked across different [GRPID]s, and should all be having the same [GRPID].
The below table is the expected result, with [NEWGRPID] populated.
ID GRPID NEWGRPID
----- ----- ------
1 345 1
1 777 1
2 777 1
3 345 1
3 777 1
4 345 1
4 999 1
5 345 1
5 877 1
6 999 1
7 877 1
8 555 2
9 555 2
Try this code:
IF OBJECT_ID('tempdb..#tmp') IS NOT NULL
BEGIN
DROP TABLE #tmp;
END;
SELECT GRPID, count (*) AS GRPCNT
INTO #tmp
FROM yourtable
GROUP BY GRPID
UPDATE TGT
SET TGT.NEWGRPID = SRC.GRPCNT
FROM yourtable TGT
JOIN #tmp ON #tmp.GRPID = TGT.GRPID
If the values are likely to change over time you should think about a computed column or a trigger.

Temp Table not working inside a Cursor to store data

Here is my cursor in side a stored Procedure
Using Temp table to store values inside the cursor
DECLARE cur CURSOR FOR SELECT * FROM #AutoDataType
OPEN cur
FETCH NEXT FROM cur INTO #Customer_Id,#First_Name
WHILE ##FETCH_STATUS = 0
BEGIN
If(NOT(#Customer_Id IS NULL))
BEGIN
Select * into #Temp_Auto from [dbo].[Auto] WHERE Customer_Id=#Customer_Id
END
FETCH NEXT FROM cur INTO #Customer_Id,#First_Name
END
CLOSE cur
DEALLOCATE cur
Select * from #Temp_Auto
why i am getting Invalid Object Name #Temp_Auto ?
How to get the values into Temp table and return back
This is my parent table:
TranId CustomerId CustomerName Time_Stamp
1 11 aaa 2015-06-05 17:39:00
2 11 aaa 2015-06-05 17:45:00
3 12 bbb 2015-06-05 17:45:00
#AutoDataType contains CustomerId
CustomerID CustomerName
11 aaa
12 bbb
what i want is get the records of customer based on id that to with Time_Stamp DESC [Latest entry]
Expected Table
TranId CustomerId CustomerName
2 11 aaa
3 22 bbb
Please guide me
This is my parent table:
TranId CustomerId CustomerName Time_Stamp
1 11 aaa 2015-06-05 17:39:00
2 11 aaa 2015-06-05 17:45:00
3 12 bbb 2015-06-05 17:45:00
4 11 aaa 2015-06-05 20:10:00
5 12 bbb 2015-06-05 20:10:00
#AutoDataType contains CustomerId
CustomerID CustomerName
11 aaa
12 bbb
what i want is get the records of customer based on ID that to with Time_Stamp DESC [Latest entry]
Expected Table
TranId CustomerId CustomerName
4 11 aaa
5 22 bbb
Only 4 and 5 TranId because their Time_Stamp is latest one.
Using a cursor here is just the wrong way to go about this. You don't need another copy of the data, it is already in your table variable. All you need is a query to get the rows you want. You need to stop thinking about looping for everything. :D
select *
from
(
SELECT a.CustomerID
, a.CustomerName
, ROW_NUMBER() over (PARTITION BY CustomerID order by TIME_STAMP desc) as RowNum
FROM [dbo].[Auto] a
JOIN #AutoDataType adt on adt.Customer_Id = a.Customer_Id
) x
where x.RowNum = 1
order by CustomerID
SELECT ... INTO creates a table with a definition to match the results of the select, then inserts into that table, thus you can only do that once for the given table. If you really want to do the above, you need to create #Temp_Auto outside the loop, then INSERT into it rather than SELECT ... INTO.
That being said, why would you even bother with the cursor? Given your code it's completely unnecessary and will perform pretty poorly compared to the alternatives. Why not just select all the rows from dbo.Auto that have a Customer_Id in #AutoDataType and insert those into the temp table?

How to use generate Id for different values in calculated columns?

I have a big query (which is already ordered as per my needs), one of the columns is calculated (varchar combination of other columns in the query). I need an incremental integer to identify this calculated column (duplicates should have the same id).
I canĀ“t use rank because the order in which I need the incremental number uses another criteria than the one used to generate the calculated column.
This is what I need:
OrderByColumn CalculatedColumn GeneratedId
1 ggg 1
1 aaa 2
1 ggg 1
1 fff 3
2 vvv 4
2 ddd 5
3 ggg 1
4 rrr 6
5 aaa 2
5 ooo 7
5 kkk 8
8 vvv 4
9 aaa 2
Use
ROW_NUMBER() OVER (PARTITION BY XXX ORDER BY YYY)
assuming you are using SQL2005 or better
http://msdn.microsoft.com/en-us/library/ms186734.aspx
-- though like you said this doesn't solve your dupes with same ID thing - ahhh! Give me a moment - should be able to do this pretty easy
Edit:
Here you go -
http://sqlfiddle.com/#!3/2f014/2
-- Select stuff:
select vals.val as genid, ord.* from ord
-- Join back to a distinct list of CalculatedColumn with a row_number() to id them
inner join
(select calculatedcolumn, row_number() over (order by calculatedcolumn) as val from ord group by calculatedcolumn) as vals on vals.calculatedcolumn = ord.calculatedcolumn
order by ord.orderbycolumn
Of course this is using the calculated column in the subquery - so you will need to re-calculate unless you store the value in a temp table or table variable

Resources