Merge records and columns - sql

Data from table A:
id desc
1 huba
1 blub
3 foo
4 bar
And I'd like to have
id desc
1 huba, blub
3 foo
4 bar
So records with the same id should be merged and the desc concatenated.
Unfortunately I can't use string or concat. I get an error if I try to use these functions.
Sybase Version:
Sybase version: Adaptive Server Enterprise/15.5/EBF 19902 SMP ESD#5.1/P/x86_64/Enterprise Linux/asear155/2594/64-bit/FBO/Wed Jun 6 01:20:27 2012

Sybase ASE does not have any functions similar to list(), group_concat(), etc.
While Sybase ASE does provide some XML support, it doesn't provide support for the 'for xml / path()' construct.
And while it's possible to create a funky workaround in ASE 16 (using a table #variable and a user-defined function) ... you're not running ASE 16.
Net result is that you'll need to write some sort of looping construct to accomplish what you want, eg, a cursor that loops through the rows in the table.
NOTE: I'd have to think about the 'merge' idea but since you're running ASE 15.5 and 'merge' isn't available until ASE 15.7 ... I'll put that idea on the back burner for now.
ps - OK, there is a single-query solution but it involves using Application Context Functions (ACFs) (eg, get_appcontext(), set_appcontext()); but that's a very, Very, VERY messy solution ...

Related

SQL Server 2014 equivalent to mysql's find_in_set()

I'm working with a database that has a locations table such as:
locationID | locationHierarchy
1 | 0
2 | 1
3 | 1,2
4 | 1
5 | 1,4
6 | 1,4,5
which makes a tree like this
1
--2
----3
--4
----5
------6
where locationHierarchy is a csv string of the locationIDs of all its ancesters (think of a hierarchy tree). This makes it easy to determine the hierarchy when working toward the top of the tree given a starting locationID.
Now I need to write code to start with an ancestor and recursively find all descendants. MySQL has a function called 'find_in_set' which easily parses a csv string to look for a value. It's nice because I can just say "find in set the value 4" which would give all locations that are descendants of locationID of 4 (including 4 itself).
Unfortunately this is being developed on SQL Server 2014 and it has no such function. The CSV string is a variable length (virtually unlimited levels allowed) and I need a way to find all ancestors of a location.
A lot of what I've found on the internet to mimic the find_in_set function into SQL Server assumes a fixed depth of hierarchy such as 4 levels maximum) which wouldn't work for me.
Does anyone have a stored procedure or anything that I could integrate into a query? I'd really rather not have to pull all records from this table to use code to individually parse the CSV string.
I would imagine searching the locationHierarchy string for locationID% or %,{locationid},% would work but be pretty slow.
I think you want like -- in either database. Something like this:
select l.*
from locations l
where l.locationHierarchy like #LocationHierarchy + ',%';
If you want the original location included, then one method is:
select l.*
from locations l
where l.locationHierarchy + ',' like #LocationHierarchy + ',%';
I should also note that SQL Server has proper support for recursive queries, so it has other options for hierarchies apart from hierarchy trees (which are still a very reasonable solution).
Finally It worked for me..
SELECT * FROM locations WHERE locationHierarchy like CONCAT(#param,',%%') OR
o.unitnumber like CONCAT('%%,',#param,',%%') OR
o.unitnumber like CONCAT('%%,',#param)

Finding the location of one string within another string in Bigquery

I couldn't find a function in BigQuery query reference which looks for one string within a second one and returns the index of the location. Something like instr() in other SQL dialects. Is there any substitute or any technique to achieve this?
For example: Looking into "de" in "abcdef" will return 4.
One way you can do this is with a Regular Expression extract (see reference here):
SELECT
title, LENGTH(REGEXP_EXTRACT(title, r'^(.*)def.*')) + 1 AS location_of_fragment
FROM
[publicdata:samples.wikipedia]
WHERE
REGEXP_MATCH(title, r'^(.*)def.*')
LIMIT 10;
Returns:
Row title location_of_fragment
1 Austrian air defense 14
2 Talk:Interface defeat 16
3 High-definition television 6
4 Talk:IAU definition of planet 10
5 Wikipedia:Articles for deletion/Culture defines politics 41
6 Wikipedia:WikiProject Spam/LinkReports/defenders.org 40
7 Adenine phosphoribosyltransferase deficiency 35
8 Stay-at-home defenceman 14
9 Manganese deficiency (plant) 11
10 High-definition television 6
The old answer is now deprecated and #carlos answer works:
STRPOS(string, substring)
The legacy SQL INSTR(str1,str2) function "Returns the one-based index of the first occurrence of a string." So that should work for you.
https://cloud.google.com/bigquery/docs/reference/legacy-sql
I'm late to the party but the BigQuery API changed, now the Regex syntax is as follow:
SELECT mydomains FROM `myproject.mydataset.mytable`
where regexp_contains(mydomains, r'^(.*)example.*');
To answer the question with For example: Looking into "de" in "abcdef" will return 4., it would look like:
SELECT de FROM `myproject.mydataset.mytable`
where regexp_contains(de, r'^(.*)abcdef.*');
REGEXP_MATCH is now part of Legacy SQL Functions and Operators as per the reference link.
Hope it helps the one! :)

how to change datatype of a column in sybase query?

One of my query to Sybase server is returning garbage data. After some investigations i found out that one of the columns with datatype double is causing the issue. If I don't select that particular column then the query returns correct result. The column is question is a double with laarge number of decimal places. I tried to use round function upto 4 decimal places but still i get corrupt data. How can I correctly specify the column in my query to get correct data?
I am using windows 7 box and Sybase Adaptive server enterprise driver. (Sybase client 15.5). I am using 32 bit drivers.
Sample results:
Incorrect result using sybase ASE driver on windows 7 box
"select ric_code as ric, adjusted_weight as adjweight from v_temp_idx_comp where index_ric_code='.AXJO' and ric_code='AQG.AX'"
ric adjweight
1 AQG.AX NA
2 \020 NA
3 <NA> NA
Correct result on windows xp box using Merant driver
"select ric_code, adjusted_weight from v_temp_idx_comp where index_ric_code='.AXJO' and ric_code='AQG.AX'"
ric_code adjusted_weight
1 AQG.AX 0.3163873547
Regards,
Alok
You may try convert to numeric like this:
select ric_code as ric, weight, convert(numeric(16,4), adjusted_weight) as adjweight, currency as currency
from v_temp_idx_comp
where index_ric_code='.AXJO'

Locating all reachable nodes using SQL

Suppose a table with two columns: From and To. Example:
From To
1 2
2 3
2 4
4 5
I would like to know the most effective way to locate all nodes that are reachable from a node using a SQL Query. Example: given 1 it would return 2,3,4 and 5. It is possible to use several queries united by UNION clauses but it would limit the number of levels that can be reached. Perhaps a different data structure would make the problem more tractable but this is what is available.
I am using Firebird but I would like have a solution that only uses standard SQL.
You can use a recursive common table expression if you use most brands of database -- except for MySQL and SQLite and a few other obscure ones (sorry, I do consider Firebird obscure). This syntax is ANSI SQL standard, but Firebird doesn't support it yet.
Correction: Firebird 2.1 does support recursive CTE's, as #Hugues Van Landeghem comments.
Otherwise see my presentation Models for Hierarchical Data with SQL for several different approaches.
For example, you could store additional rows for every path in your tree, not just the immediate parent/child paths. I call this design Closure Table.
From To Length
1 1 0
1 2 1
1 3 2
1 4 2
1 5 3
2 2 0
2 3 1
2 4 1
3 3 0
4 4 0
4 5 1
5 5 0
Now you can query SELECT * FROM MyTable WHERE From = 1 and get all the descendants of that node.
PS: I'd avoid naming a column From, because that's an SQL reserved word.
Unfortunately there isn't a good generic solution to this that will work for all situations on all databases.
I recommend that you look at these resources for a MySQL solution:
Managing Hierarchical Data in MySQL
Models for hierarchical data - presentation by Bill Karwin which discusses this subject, demonstrates different solutions, and compares the adjacency list model you are using with other alternative models.
For PostgreSQL and SQL Server you should take a look at recursive CTEs.
If you are using Oracle you should look at CONNECT BY which is a proprietary extension to SQL that makes dealing with tree structures much easier.
With standard SQL the only way to store a tree with acceptable read performance is by using a hack such as path enumeration. Note that this is very heavy on writes.
ID PATH
1 1
2 1;2
3 1;2;3
4 1;2;4
SELECT * FROM tree WHERE path LIKE '%2;%'

SQL to retrieve tree structure nicely

Given the simple data structure:
ID | Category_Name | Parent_ID
Example:
1 Cars 0
2 Boxes 0
3 Lamborghinis 1
4 VW Camper Vans 1
5 Big Boxes 2
6 Small Boxes 2
7 Cereal Boxes 2
8 Broken Lambos 3
9 Yellow Ones 3
10 Rusty 8
11 Milkshake Stained 8
12 Chocolate Flavour 11
13 Strawberry 11
14 Indiscernible Solution 11
Representing a simple tree navigation structure, what would programatically be the best way to retrieve the tree in a presentable format? Can we create an SQL statement to retrieve them 'in order'?
Thanks for any help! If my approach is wrong, feel free to comment also.
I'm using SQL-Server 2000.
If you're using SQL Server 2008 you might want to try out the new hierarchyid data type.
If you're not then another way is to look into the nested sets model which works on all databases.
If you're using SQL Server 2005 and up you can use recursive CTEs to retreive the tree structure.
I usually build the tree structure in my application code. Partially because I'm more confident with c# than SQL, but it also because I usually need to process the data into suitable c# structures anyway.
SQL is quite bad at recursive structures like lists and trees. If I had to put the tree building in my database I'd go for a stored procedure. But there might be a smart way I don't know about.
If you use Oracle you might be able to hack something up with Connect By.
Not for SQL2000, but if you manage to upgrade to 2k5, you can do
WITH t AS(SELECT id, parent_id, category_name FROM mytable WHERE parent_id IS NULL
UNION ALL
SELECT c.id, c.parent_id, c.category_name FROM t p JOIN mytable c ON c.parent_id = p.id)
SELECT * FROM t