How to unstruct a Struct in SQL - sql

I have a struct in a table (Iceberg Database format) and I would like to expand all of the children of the struct.
The normal query would look like :
SELECT
base.el1,
base.el2,
base.el3
FROM myTable
Instead of that, I would like to have a statement as the following: (not working - just an idea)
Select
base.*
FROM myTable
That would return
el1
el2
el3
One
Two
Three
Is it possible to realize such statement?
In real-life I have like hundreds of elements and do not wish write all of them down.
If I do the proposed (not-working) statement.
It returns something like:
col1
(One,Two,Three)

Do you just want to concatenate the columns like this?
select concat(el1,',',el2,',',el3) as b from a;
https://www.db-fiddle.com/f/cqusK23oVYcTBvD4cv9GoA/0

Apparently, it just works with the following statement:
Select
base.*
FROM myTable
For some reason it was returning an erroronous result but not from my part of the Query statement.

Related

How to select a column whose name is a value in another column in POSTGRESQL?

I know this isn't valid SQL, but I'd like to do something like:
SELECT items.{SELECT items.preferred_column}
To elaborate, to achieve what I'm trying to achieve, I could write a long case when statement:
SELECT
CASE WHEN items.preferred_column = "column_a" THEN items.column_a
CASE WHEN items.preferred_column = "column_b" THEN items.column_b
CASE WHEN items.preferred_column = "column_c" THEN items.column_c
... and so on...
But that seems wrong. I would prefer to write a query that looks at the value of items.preferred_column and loads that column.
Is this possible?
My use case involves an Active Record (the ORM for Rails) query, which limits me. I'm not able to use "INTO" for example.
Doing this without creating a SQL function would preferred, though if it's not possible without creating a SQL function that would be good to know.
Thanks in advance for lending your expertise!
You can try transforming the table rows with row_to_json() and then using json_each(), you can join the resultant "key" field on the preferred_column:
WITH CTE AS (
SELECT
row_to_json(Z.*)::jsonb as rcr,
row_number() over(partition by null order by <whatever comparator clause>) as rn,
Z.*
FROM items Z)
SELECT b.value, a.*
FROM CTE a, jsonb_each(rcr) b, CTE c
WHERE c.rn=a.rn AND b.key = ( c.preferred_column )
Note that this essentially operates as a quasi-pivot, so you'll need to maintain an index (the row_number invocation) to self-join the table when extracting the appropriate key-value pairs from jsonb_each's set-return. Casting to jsonb will be helpful in that the binary form will alphabetize the key-value pairs by key order within the object itself.
If you need to get the resultant value as a text string instead of a json primitive, you can do
b.value #>>'{}'
instead of using jsonb_each_text(), which will preserve any json columns.

Using CONTAINS to find items IN a table

I'm trying to write a SP that will allow users to search on multiple name strings, but supports LIKE functionality. For example, the user's input might be a string 'Scorsese, Kaurismaki, Tarkovsky'. I use a split function to turn that string into a table var, with one column, as follows:
part
------
Scorsese
Kaurismaki
Tarkovsky
Then, normally I would return any values from my table matching any of these values in my table var, with an IN statement:
select * from myTable where lastName IN (select * from #myTableVar)
However, this only returns exact matches, and I need to return partial matches. I'm looking for something like this, but that would actually compile:
select * from myTable where CONTAINS(lastName, select * from #myTableVar)
I've found other questions where it's made clear that you can't combine LIKE and IN, and it's recommended to use CONTAINS. My specific question is, is it possible to combine CONTAINS with a table list of values, as above? If so, what would that syntax look like? If not, any other workarounds to achieve my goal?
I'm using SQL Server 2016, if it makes any difference.
You can use EXISTS
SELECT * FROM myTable M
WHERE
EXISTS( SELECT * FROM #myTableVar V WHERE M.lastName like '%'+ V.part +'%' )
Can your parser built the entire statement? Will that get you what you want?
select *
from myTable
where CONTAINS
(lastName,
'"Scorsese" OR "Kaurismaki" OR "Tarkovsky"'
)
This can be done using CHARINDEX function combined with EXISTS:
select *
from myTable mt
where exists(select 1 from #myTableVar
where charindex(mt.lastName, part) > 0
or charindex(part, mt.lastName) > 0)
You might want to omit one of the conditions in the inner query, but I think this is what you want.

SQL. When I trying to do something like "INSERT INTO Table VALUES(x1,x2,x3) - can the x1 x2 x3 be sql queries, like SELECT <...>

I want to do something like this:
QSqlQuery q;
q.prepare("insert into Norm values(select from Disc id_disc WHERE name_disc=?, select from Spec code_spec WHERE name_spec=?,?");
q.addBindValue(MainModel->data(MainModel->index(MainModel->rowCount()-1, 1)).toString());
q.addBindValue(ui->comboBox->currentText());
q.addBindValue(MainModel->data(MainModel->index(MainModel->rowCount()-1, 2)).toString());
q.exec();
But it's not working. Surely for someone obviously where is the error and maybe he tells me how to do it right.
First of all your you have done spelling mistake. Its "INSERT" not "INCERT"
And yes we can insert SELECT query inside INSERT query.
eg:
INSERT INTO table2
(column_name(s))
SELECT column_name(s)
FROM table1;
INSERT ... SELECT ... is used when you want to insert multiple records, or when most values to be inserted come from the same record.
If you want to insert one record with values coming from several tables, you can use subqueries like you tried to do, but you have to use the correct syntax:
scalar subqueries must be written inside parentheses, and you must write the SELECT correctly as SELECT value FROM table:
INSERT INTO Norm
VALUES ((SELECT id_disc FROM Disc WHERE name_disc = ?),
(SELECT code_spec FROM Spec WHERE name_spec = ?),
?)
If you want data from two tables, you must first write a query which return pretended data - using JOIN, UNION, subqueries, ...
Then, just do
INSERT INTO target_table SELECT ...

sql statement inside decode clause

The decode works like this:
SELECT DECODE('col1', 'x', 'result1','y','result2') resultFinal
FROM table1;
It possible to accomplish this in sql:
SELECT *
FROM (SELECT DECODE('col1', 'x' (someSql),'y',(someOthersql)) result
FROM table1)
So instead of result1 and result2 being fixed values, they would be sql statements. If not possible, how can I achieve the same result without a stored proc.
EDIT: someSql and someOthersql are both complex queries with many joins returining many but same number of cols with same col names.
If someSql and someOthersql return exactly one row with one column, then this should work.
The following works for me:
select decode(col, (select 'foo' from dual), (select 'bar' from dual))
from some table
I think you may need to create a PL/SQL procedure to handle the complex logic.

Is there any way to combine IN with LIKE in an SQL statement?

I am trying to find a way, if possible, to use IN and LIKE together. What I want to accomplish is putting a subquery that pulls up a list of data into an IN statement. The problem is the list of data contains wildcards. Is there any way to do this?
Just something I was curious on.
Example of data in the 2 tables
Parent table
ID Office_Code Employee_Name
1 GG234 Tom
2 GG654 Bill
3 PQ123 Chris
Second table
ID Code_Wildcard
1 GG%
2 PQ%
Clarifying note (via third-party)
Since I'm seeing several responses which don't seems to address what Ziltoid asks, I thought I try clarifying what I think he means.
In SQL, "WHERE col IN (1,2,3)" is roughly the equivalent of "WHERE col = 1 OR col = 2 OR col = 3".
He's looking for something which I'll pseudo-code as
WHERE col IN_LIKE ('A%', 'TH%E', '%C')
which would be roughly the equivalent of
WHERE col LIKE 'A%' OR col LIKE 'TH%E' OR col LIKE '%C'
The Regex answers seem to come closest; the rest seem way off the mark.
I'm not sure which database you're using, but with Oracle you could accomplish something equivalent by aliasing your subquery in the FROM clause rather than using it in an IN clause. Using your example:
select p.*
from
(select code_wildcard
from second
where id = 1) s
join parent p
on p.office_code like s.code_wildcard
In MySQL, use REGEXP:
WHERE field1 REGEXP('(value1)|(value2)|(value3)')
Same in Oracle:
WHERE REGEXP_LIKE(field1, '(value1)|(value2)|(value3)')
Do you mean somethign like:
select * FROM table where column IN (
SELECT column from table where column like '%%'
)
Really this should be written like:
SELECT * FROM table where column like '%%'
Using a sub select query is really beneficial when you have to pull records based on a set of logic that you won't want in the main query.
something like:
SELECT * FROM TableA WHERE TableA_IdColumn IN
(
SELECT TableA_IdColumn FROM TableB WHERE TableA_IDColumn like '%%'
)
update to question:
You can't combine an IN statement with a like statement:
You'll have to do three different like statements to search on the various wildcards.
You could use a LIKE statement to obtain a list of IDs and then use that in the IN statement.
But you can't directly combine IN and LIKE.
Perhaps something like this?
SELECT DISTINCT
my_column
FROM
My_Table T
INNER JOIN My_List_Of_Value V ON
T.my_column LIKE '%' + V.search_value + '%'
In this example I've used a table with the values for simplicity, but you could easily change that to a subquery. If you have a large list (like tens of thousands) then performance might be rough.
select *
from parent
where exists( select *
from second
where office_code like trim( code_wildcard ) );
Trim code_wildcard just in case it has trailing blanks.
You could do the Like part in a subquery perhaps?
Select * From TableA Where X in (Select A from TableB where B Like '%123%')
tsql has the contains statement for a full-text-search enabled table.
CONTAINS(Description, '"sea*" OR "bread*"')
If I'm reading the question correctly, we want all Parent rows that have an Office_code that matches any Code_Wildcard in the "Second" table.
In Oracle, at least, this query achieves that:
SELECT *
FROM parent, second
WHERE office_code LIKE code_wildcard;
Am I missing something?