Select from array in postgres using wildcard/Like - arrays

So I have a Postgres database where one of the columns is an array of strings
If I do the query
SELECT count(*) FROM table WHERE column #> ARRAY['string']::varchar[];
I get a certain set of data back, but if I want to query that array with a wildcard on the string I can't seem to figure that out, something like
SELECT count(*) FROM table WHERE column LIKE ARRAY['%string%']::varchar[];
Any help is appreciated!

use unnest():
WITH t(arr) AS ( VALUES
(ARRAY['foo','bar']),
(ARRAY['foo1','bar1'])
)
SELECT count(*) FROM t,unnest(t.arr) AS str
WHERE str ILIKE '%foo%';
Result:
count
-------
2
(1 row)

Related

Group by based on specific column contains value from list of values

I've one table myTable
ID
Content
1
Hello, this is the test content
2
Hi, test content.
I have one list having different values = ["Hello","Hi","Yes","content"]
Now I have to find occurrence of value in myTable-> content column & resultant table have value & count of that value in myTable-> content column (one row of myTable table can have more than one values & use case-insensitive search).
Output be like:
Value
Count
Hello
1
Hi
1
Yes
0
content
2
I want to make optimal SQL server query.
Assuming you are using SQL Server 2016 or above, you could try converting your list to a table like structure, and perform a left join and count on your table.
For instance :
CREATE TABLE MyTable (
ID INT CONSTRAINT PK_MyTable PRIMARY KEY,
Content NVARCHAR(MAX)
);
INSERT INTO MyTable (ID,CONTENT) VALUES
(1,'Hello, this is the test content'),
(2,'Hi, test content.');
DECLARE #MyList NVARCHAR(MAX)
SET #MyList='["Hello","Hi","Yes","content"]';
SELECT
List.Value,
COUNT(MyTable.Content) Count
FROM OPENJSON(#MyList) List --Convert the list to a json
LEFT JOIN MyTable ON '.' + UPPER(MyTable.Content) + '.' LIKE '%[^a-z]' + UPPER(List.Value) +'[^a-z]%'
GROUP BY List.Value;
You can try it on this fiddle.
Please do note that there is margin for improvement, such as full text index instead of this ugly regular expression clause.
See also :
Search for “whole word match” with SQL Server LIKE pattern

Snowflake Array to String issue

In Snowflake database, I'm trying to extract string from an array column.
The name of the column in the table is: mbus.
So, if you query the table:
select PRO.JSON_DATA:mbus
FROM SOURCE_TABLE1 PRO
the result will be:
[{"region":"EAME"},{"region":"LA"},[{"region":"NA"},[{"region":"NAP"},[{"region":"SAP"}]
I'm using ARRAY_TO_STRING function:
SELECT ARRAY_TO_STRING(PRO.JSON_DATA:mbus:region, ', ')
FROM SOURCE_TABLE1 PRO
, but the result is NULL.
The final result should be: EAME, LA, NA, NAP, SAP (Extracting from the column).
Could you help me on this one? I need to build a query to extract the properly strings from the array.
Using FLATTEN to transform json to rows and LISTAGG to combine back to single string:
SELECT LISTAGG(f.value:region::STRING, ',') AS col
FROM SOURCE_TABLE1 PRO
,LATERAL FLATTEN(input => PRO.JSON_DATE:mbus) f

Determine if columns have duplicate values sql

I am trying to figure out a way to check if their is repeated values in rows that are shared.
Example:
HMOID Name Addon10 Addon15 Addon20
RFFF Blah img path1 img path2 img path1
For my example, I would like to check if any of the addons for RFFF have any repeated value. In my example above, 'RFFF' has two images that are the same in Addon10 and Addon20 (The images have a path. so currently, they look like
http://oc2-reatest.regalmed.local/ocupgrade52/images/NDL_SCAN_SR.PNG).
I would like to be able to do this for multiple rows. I thought the following would give me an idea how to begin:
select * from HlthPlan
Group By HMO1A, HMONM
Having COUNT(*) > 1
However, it throughs the following error:
Msg 8120, Level 16, State 1, Line 1
Column 'HlthPlan.HMOID' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.*
I am fairly new to SQL and any suggestions would be appreciated.
Don't include * for your select query. Only include the columns that you are using in GROUP BY
SELECT HMO1A, HMONM, COUNT(*) from HlthPlan
GROUP BY HMO1A, HMONM
HAVING COUNT(*) > 1;
With only three columns to check, assuming non-null values across a single row:
select * from HlthPlan
where Addon10 in (Addon15, Addon20) or Addon15 = Addon20
You can also use cross apply to pivot the values for grouping:
select HMOID, addon
from HlthPlan cross apply (
select addon
from (values (Addon01), (Addon02), (Addon03), ... (Addon20)) as pvt(addon)
) a
where addon is not null
group by HMOID, addon
having count(*) > 1;
http://rextester.com/QWIW87618
You'll get multiple rows for each HMOID where the are different groups of columns having the same value. By the way, reporting on the names of specific columns involved would add another degree of difficulty to the query.
One way you can check for this is using UNPIVOT to compare your results:
create table #hmo (hmoid varchar(6), name varchar(25), Addon10 varchar(25),
Addon15 varchar(25), addon20 varchar(25));
insert into #hmo
values ('RFFF', 'Blah','img path1', 'img path2', 'img path1');
select hmoid, name, addval, addcount = count(adds)
FROM #hmo
UNPIVOT
(
addval FOR adds IN
(addon10, addon15, addon20)
) as unpvt
group by hmoid, name, addval having count(*) > 1
Will give results:
hmoid name addval addcount
RFFF Blah img path1 2
This way you can check against every row in the table and will see any row that has any two or more columns with the same value.
This does have the potential to get tedious if you have a lot of columns; the easiest way to correct for that is to build your query dynamically using info from sys.tables and sys.columns.

use variable in select - tsql

Hi I have procedure which have parameter(#identFormat)
Example
"GUID"
"LotID|FeatureID"
And now I have Select query which should split this and use as columns.
Moreover result should be back combined.
Example:
Table:
Id LotID FeatureID
2 1 4
3 4 5
4 2 1
and if my #identFormat = "LotID|FeatureID" then it should return
Table:
1|4
4|5
2|1
Actually I have ncharchar #columns 'LotId + "|" + FeatureId'
Is it possible to use this like this:
Select #columns from Table ?
or using dynamic sql
EDIT:
Unfortunately combination of columns can be different. My purpose is send column names to procedure and select this columns from specific table. This is procedure to save data , but if something went wrong I must save this unique combination of columns in second table.
Unfortunatelly, it is not possible. You need to select separately and format the output

Performance of PIVOT and MERGE - is there a better way I can do this?

Sorry, this might be a bit out of scope for the community here, but I wanted to get a second opinion.
I have a table with the following structure
Table_1
TYPE ITEM DATE QTYA QTYB QTYC
X AAA 17/08/2015 100 200 300
X AAA 18/08/2015 100 170 240
Y BBB 17/08/2015 100 240 100
I need to use this table as a source for a merge, but the target table is formatted completely differently
Table_2
ITEM QTYA_1 QTYA_2......QTYA_31 QTYB_1 QTYB_2 QTYB_3......QTYB_31 QTYC_1 QTYC_2....QTYC_31
(the numbers suffixed at basically the day of the month)
I can convert Table 1 to the format of Table 2 using a mix of UNION ALL and PIVOT, but the performance isn't that good - particularly since I have to save the information in a temp table first before merging it in (Each 'type' in Table_1 has a different start date and I cannot overwrite previous values in Table_2 starting from a different date - basically I have to merge the table 3 or 4 times with a different item type and different start date)
Here's what I got so far
SELECT TOP 0 * INTO #TEMP_PIVOT_TABLE
INSERT INTO #TEMP_PIVOT_TABLE SELECT * FROM
(SELECT ITEM, 'QTYA_' + CONVERT(DATETIMEFROMPARTS(day,DATE) AS VARCHAR) as 'Quantity Type', QTY_A FROM TABLE_1
UNION_ALL
SELECT ITEM, 'QTYB_' + CONVERT(DATETIMEFROMPARTS(day,DATE) AS VARCHAR) as 'Quantity Type', QTY_B FROM TABLE_1
UNION_ALL
SELECT ITEM, 'QTYC_' + CONVERT(DATETIMEFROMPARTS(day,DATE) AS VARCHAR) as 'Quantity Type', QTY_C FROM TABLE_1
) A
PIVOT
(SUM(QUANTITY) FOR QUANTITY_TYPE IN ([QTYA_1], [QTYA_2],.....[QTYA_31],[QTYB_1].....[QTYC_31],[QTYC_1].....[QTYC_31])) AS B
----For each different date per item_type, construct a string only selecting those days in the month.
Then merge the results from #TEMP_PIVOT_TABLE into TABLE_2 for each Item TYPE` with dynamic SQL
1) Is there any better way to do the PIVOT command? The performance of the UNION ALL commands isn't encouraging - particularly since the table I'm reading from has large amounts of data. I'm also simplifying here for the sake of brevity - the actual table needs to map 5 columns or so, each with 31 days
2) Is there a better way to do the MERGE? I dislike using a loop + Dynamic SQL to basically read the same dataset repeatedly just so to merge on different columns, but I can't see a different way. That and building the MERGE command dynamically with so many columns will make it troublesome for future maintenance.
Does anyone have an idea how I can go about this more efficiently?
You can replace the union all internal query with the following query. This query needs only one table hit instead of hitting table for each column.
To unpivot the data use cross apply with table valued constructor
select ITEM,[Quantity Type],QTY
from yourtable
cross apply
(
values
('QTYA_' + CONVERT(DATEPART(day,DATE) AS VARCHAR),QTY_A),
('QTYB_' + CONVERT(DATEPART(day,DATE) AS VARCHAR),QTY_B),
('QTYC_' + CONVERT(DATEPART(day,DATE) AS VARCHAR),QTY_C),
)
CS ([Quantity Type],QTY)

Resources