compare column with text array in postgressql - database

We have a PostgreSQL database where I have two tables with column text[] datatype. When I use an inner join to get details I do not see it is matching with any row.
for e.g.
create table test{
names text[],
id
}
create table test_b{
names text[],
id
}
now when I run below query,
SELECT t.* from test t inner join test_b tt
where t.names=tt.names;
I don't see any results. I even tried normal query with
SELECT * FROM test where names='{/test/test}';
It also did not work.
Any suggestions?

I suspect that you want array overlap operator &&. Also, since you don't need to return anything from test_b, using exists with a correlated subquery is more relevant than a join:
select t.*
from test t
where exists (select 1 from test_b b where t.names && b.names)

Related

SQL Server: how to omit 'CreatedOn' column while creating a temp table?

I have a query (similar to the one below) that supposed to create a temporary table from a join:
SELECT p.pid,*
INTO #temp_insert_inventory
FROM
(SELECT *
FROM main_inventory.dbo.Inv i
LEFT JOIN web_inventory.dbo.Variant v ON i.id = v.ext4
WHERE v.ext4 IS NULL
AND i.qty > 0) PL
INNER JOIN web_inventory.dbo.Product p ON PL.invcode = p.ext
The problem is that SQL Server is refusing to create the temporary table because there are multiple CreatedOn columns being returned from the select.
I really don't need any one of these columns so how can I just omit it in the select?
Thanks!
List out all the columns instead of SELECT *.
If you need both versions of the conflicting CreatedOn columns, you can use an alias for one of them. If you don't want the additional column at all then don't include it in the SELECT list.
Bad Habits to Kick: Using SELECT * / omitting the column list

How to use a table valued function in select clause?

I have a tableA with one of the string columns (rawData) and I have a table-valued function (functionA) that functions will accept 'rawData' as an input parameter and returns five new fields. what will that function do? - this will do some string manipulation and split some data into five values
My motive is to select that string column (rawData) and also pass that table-valued function (functionA) and get those five new fields for every row in tableA
Here is the sample:
Select
(Select * from function (rawData))
from tableA
my expectations are I should get every row with that values from functionA along with rawData, but I'm getting below error:
Only one expression can be specified in the select list when the
subquery is not introduced with EXISTS.
How do I achieve this?
You would use a CROSS APPLY:
SELECT a.rawData, b.*
FROM TableA a
CROSS APPLY FunctionA(a.rawdata) b
Okay, first off, let's examine why you are getting an error. What is wrong with your syntax?
Well, a subquery in the select clause is expected to return at most one column. Your subquery, by using *, is returning all of the columns from the results of your function call, which appears to be more than one in this case.
Next, what are you trying to accomplish? It looks like you are trying to take the value of a column from tableA and apply functionA to the value in that column for each row returned from tableA.
The proper syntax to accomplish that is by using an apply. There is both cross apply and outer apply. The difference between them is like the difference between an inner join and a left join (or left outer join).
In other words, for the cross apply, if no rows are returned from the call to functionA for a particular row from tableA, then that row from tableA will not be included. For the outer apply, that case would be reversed, as the row from tableA would still be included, just the columns from the function call would be null.
An example query with this syntax based on the query in your question would be the following:
select fa.*
from tableA ta
outer apply functionA(ta.rawData) fa;
Note that I used an outer apply in my example, since your query didn't seem to be expecting rows from tableA with no rows returned from functionA to be excluded.

String or binary data would be truncated error in SQL server. How to know the column name throwing this error

I have an insert Query and inserting data using SELECT query and certain joins between tables.
While running that query, it is giving error "String or binary data would be truncated".
There are thousands of rows and multiple columns I am trying to insert in that table.
So it is not possible to visualize all data and see what data is throwing this error.
Is there any specific way to identify which column is throwing this error? or any specific record not getting inserted properly and resulted into this error?
I found one article on this:
RareSQL
But this is when we insert data using some values and that insert is one by one.
I am inserting multiple rows at the same time using SELECT statements.
E.g.,
INSERT INTO TABLE1 VALUES (COLUMN1, COLUMN2,..) SELECT COLUMN1, COLUMN2,.., FROM TABLE2 JOIN TABLE3
Also, in my case, I am having multiple inserts and update statements and even not sure which statement is throwing this error.
You can do a selection like this:
select TABLE2.ID, TABLE3.ID TABLE1.COLUMN1, TABLE1.COLUMN2, ...
FROM TABLE2
JOIN TABLE3
ON TABLE2.JOINCOLUMN1 = TABLE3.JOINCOLUMN2
LEFT JOIN TABLE1
ON TABLE1.COLUMN1 = TABLE2.COLUMN1 and TABLE1.COLUMN2 = TABLE2.COLUMN2, ...
WHERE TABLE1.ID = NULL
The first join reproduces the selection you have been using for the insert and the second join is a left join, which will yield null values for TABLE1 if a row having the exact column values you wanted to insert does not exist. You can apply this logic to your other queries, which were not given in the question.
You might just have to do it the hard way. To make it a little simpler, you can do this
Temporarily remove the insert command from the query, so you are getting a result set out of it. You might need to give some of the columns aliases if they don't come with one. Then wrap that select query as a subquery, and test likely columns (nvarchars, etc) like this
Select top 5 len(Col1), *
from (Select col1, col2, ... your query (without insert) here) A
Order by 1 desc
This will sort the rows with the largest values in the specified column first and just return the rows with the top 5 values - enough to see if you've got a big problem or just one or two rows with an issue. You can quickly change which column you're checking simply by changing the column name in the len(Col1) part of the first line.
If the subquery takes a long time to run, create a temp table with the same columns but with the string sizes large (like varchar(max) or something) so there are no errors, and then you can do the insert just once to that table, and run your tests on that table instead of running the subquery a lot
From this answer,
you can use temp table and compare with target table.
for example this
Insert into dbo.MyTable (columns)
Select columns
from MyDataSource ;
Become this
Select columns
into #T
from MyDataSource;
select *
from tempdb.sys.columns as TempCols
full outer join MyDb.sys.columns as RealCols
on TempCols.name = RealCols.name
and TempCols.object_id = Object_ID(N'tempdb..#T')
and RealCols.object_id = Object_ID(N'MyDb.dbo.MyTable)
where TempCols.name is null -- no match for real target name
or RealCols.name is null -- no match for temp target name
or RealCols.system_type_id != TempCols.system_type_id
or RealCols.max_length < TempCols.max_length ;

Postgresql Select from values in array

i am converting multiple rows in to a array using array_agg() function,
and i need to give that array to a select statements where condition.
My query is,
SELECT * FROM table WHERE id =
ALL(SELECT array_agg(id) FROM table WHERE some_condition)
but it gives error, how can i over come it..
the error has been cleared by type casting the array, using my query like this
SELECT * FROM table WHERE id =
ALL((SELECT array_agg(id) FROM table WHERE some_condition)::bigint[])
reference link
It seems like you are over-complicating things. As far as I can tell, your query should be equivalent to simple:
SELECT * FROM table WHERE some_condition
Or, if you are selecting from 2 different tables, use join:
SELECT table1.*
FROM table1
JOIN table2 ON table1.id = table2.id
WHERE some_condition
Not only this is simpler, it is also faster than fiddling with arrays.

SQL WHERE NOT EXISTS (skip duplicates)

Hello I'm struggling to get the query below right. What I want is to return rows with unique names and surnames. What I get is all rows with duplicates
This is my sql
DECLARE #tmp AS TABLE (Name VARCHAR(100), Surname VARCHAR(100))
INSERT INTO #tmp
SELECT CustomerName,CustomerSurname FROM Customers
WHERE
NOT EXISTS
(SELECT Name,Surname
FROM #tmp
WHERE Name=CustomerName
AND ID Surname=CustomerSurname
GROUP BY Name,Surname )
Please can someone point me in the right direction here.
//Desperate (I tried without GROUP BY as well but get same result)
DISTINCT would do the trick.
SELECT DISTINCT CustomerName, CustomerSurname
FROM Customers
Demo
If you only want the records that really don't have duplicates (as opposed to getting duplicates represented as a single record) you could use GROUP BY and HAVING:
SELECT CustomerName, CustomerSurname
FROM Customers
GROUP BY CustomerName, CustomerSurname
HAVING COUNT(*) = 1
Demo
First, I thought that #David answer is what you want. But rereading your comments, perhaps you want all combinations of Names and Surnames:
SELECT n.CustomerName, s.CustomerSurname
FROM
( SELECT DISTINCT CustomerName
FROM Customers
) AS n
CROSS JOIN
( SELECT DISTINCT CustomerSurname
FROM Customers
) AS s ;
Are you doing that while your #Tmp table is still empty?
If so: your entire "select" is fully evaluated before the "insert" statement, it doesn't do "run the query and add one row, insert the row, run the query and get another row, insert the row, etc."
If you want to insert unique Customers only, use that same "Customer" table in your not exists clause
SELECT c.CustomerName,c.CustomerSurname FROM Customers c
WHERE
NOT EXISTS
(SELECT 1
FROM Customers c1
WHERE c.CustomerName = c1.CustomerName
AND c.CustomerSurname = c1.CustomerSurname
AND c.Id <> c1.Id)
If you want to insert a unique set of customers, use "distinct"
Typically, if you're doing a WHERE NOT EXISTS or WHERE EXISTS, or WHERE NOT IN subquery,
you should use what is called a "correlated subquery", as in ypercube's answer above, where table aliases are used for both inside and outside tables (where inside table is joined to outside table). ypercube gave a good example.
And often, NOT EXISTS is preferred over NOT IN (unless the WHERE NOT IN is selecting from a totally unrelated table that you can't join on.)
Sometimes if you're tempted to do a WHERE EXISTS (SELECT from a small table with no duplicate values in column), you could also do the same thing by joining the main query with that table on the column you want in the EXISTS. Not always the best or safest solution, might make query slower if there are many rows in that table and could cause many duplicate rows if there are dup values for that column in the joined table -- in which case you'd have to add DISTINCT to the main query, which causes it to SORT the data on all columns.
-- Not efficient at all.
And, similarly, the WHERE NOT IN or NOT EXISTS correlated subqueries can be accomplished (and give the exact same execution plan) if you LEFT OUTER JOIN the table you were going to subquery -- and add a WHERE . IS NULL.
You have to be careful using that, but you don't need a DISTINCT. Frankly, I prefer to use the WHERE NOT IN subqueries or NOT EXISTS correlated subqueries, because the syntax makes the intention clear and it's hard to go wrong.
And you do not need a DISTINCT in the SELECT inside such subqueries (correlated or not). It would be a waste of processing (and for WHERE EXISTS or WHERE IN subqueries, the SQL optimizer would ignore it anyway and just use the first value that matched for each row in the outer query). (Hope that makes sense.)

Resources