SQL Statement Insert Into - sql

I'm getting the following no matter what I do any help would be awesome.
Msg 116, Level 16, State 1, Line 15
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
Msg 109, Level 15, State 1, Line 1
There are more columns in the INSERT statement than values specified in the VALUES clause. The number of values in the VALUES clause must match the number of columns specified in the INSERT statement.
My query
[tableA].[PROJECTID],
[tableA].[STUDYID],
[tableA].[SUBJNO],
[tableA].[CASENUMBER],
[tableA].[CASESTATUS],
[tableA].[MODIFIEDBY]
)VALUES((
SELECT b.PROJECTID,
((SELECT TOP 1 a.STUDYID FROM [PRODVIEW] a WHERE a.DYNAME = b.DYNAME and
a.ProjID = b.PROJID)) as STUDYID,
b.SUBJNO,
(b.SUBJNO + '_' + b.SEQUENCE) as CaseNumber,
'READY' as CASESTATUS,
b.UPLOADEDBY
FROM [dbo].[TableB] b WHERE VIEWED = 0
AND b.UPLOADEDDATE >= DATEADD(day, DATEDIFF(day, 0, GETDATE()), 0)))

If you want to use a SELECT as the source of the data for an INSERT, then don't use VALUES, which is for inserting literal data:
INSERT INTO yourTable ([PROJECTID], [STUDYID], [SUBJNO], [CASENUMBER], [CASESTATUS],
[MODIFIEDBY])
SELECT
b.PROJECTID,
(SELECT TOP 1 a.STUDYID FROM [PRODVIEW] a
WHERE a.DYNAME = b.DYNAME and a.ProjID = b.PROJID),
b.SUBJNO,
(b.SUBJNO + '_' + b.SEQUENCE),
'READY',
b.UPLOADEDBY
FROM [dbo].[TableB] b
WHERE
VIEWED = 0 AND
b.UPLOADEDDATE >= DATEADD(day, DATEDIFF(day, 0, GETDATE()), 0);
There is probably a way to write your query without using a correlated subquery in the select clause, e.g. via a join. Actually, your subquery with TOP makes no sense because there is no ORDER BY clause.
Also note that you don't need to use aliases in the SELECT statement. In fact, they will just be ignored, since the INSERT determines the target columns.

Related

Snowflake - update with correlated subquery using timediff

I am running this query on Snowflake Database:
UPDATE "click" c
SET "Registration_score" =
(SELECT COUNT(*) FROM "trackingpoint" t
WHERE 1=1
AND c."CookieID" = t."CookieID"
AND t."page" ilike '%Registration complete'
AND TIMEDIFF(minute,c."Timestamp",t."Timestamp") < 4320
AND TIMEDIFF(second,c."Timestamp",t."Timestamp") > 0);
The Database returns Unsupported subquery type cannot be evaluated. However, if I run it without the last two conditions (with TIMEDIFF), it works without problem. I confirmed that the actual TIMEDIFF statements are alright with these queries:
select count(*) from "trackingpoint"
where TIMEDIFF(minute, '2018-01-01', "Timestamp") > 604233;
select count(*) from "click"
where TIMEDIFF(minute, '2018-01-01', "Timestamp") > 604233;
and these work without problem. I don't see a reason why the TIMEDIFF condition shoud prevent the database from returning the result. Any idea what should I alter to make it work?
so using the following setup
create table click (id number,
timestamp timestamp_ntz,
cookieid number,
Registration_score number);
create table trackingpoint(id number,
timestamp timestamp_ntz,
cookieid number,
page text );
insert into click values (1,'2018-03-20', 101, 0),
(2,'2019-03-20', 102, 0);
insert into trackingpoint values (1,'2018-03-20 00:00:10', 101, 'user reg comp'),
(2,'2018-03-20 00:00:11', 102, 'user reg comp'),
(3,'2018-03-20 00:00:13', 102, 'pet reg comp'),
(4,'2018-03-20 00:00:15', 102, 'happy dance');
you can see we get the rows we expect
select c.*, t.*
from click c
join trackingpoint t
on c.cookieid = t.cookieid ;
now there are two ways to get your count, the first as you have it, which is good if your counting only one thing, as all the rules are join filtering:
select c.id,
count(1) as new_score
from click c
join trackingpoint t
on c.cookieid = t.cookieid
and t.page ilike '%reg comp'
and TIMEDIFF(minute, c.timestamp, t.timestamp) < 4320
group by 1;
or you can (in snowflake syntax) move the count to the aggregate/select side,and thus get more than one answer if that's what you need (this is the place I find myself more, thus why I present it):
select c.id,
sum(iff(t.page ilike '%reg comp' AND TIMEDIFF(minute, c.timestamp, t.timestamp) < 4320, 1, 0)) as new_score
from click c
join trackingpoint t
on c.cookieid = t.cookieid
group by 1;
thus plugging this into the UPDATE pattern (see last example in the doc's)
https://docs.snowflake.net/manuals/sql-reference/sql/update.html
you can move to a single subselect instead of a corolated subquery which snowflake doesn't support, which is the error message you are getting.
UPDATE click c
SET Registration_score = s.new_score
from (
select ic.id,
count(*) as new_score
from click ic
join trackingpoint it
on ic.cookieid = it.cookieid
and it.page ilike '%reg comp'
and TIMEDIFF(minute, ic.timestamp, it.timestamp) < 4320
group by 1) as s
WHERE c.id = s.id;
The reason add the TIMEDIFF turns your query into a correlated sub-query, is each row of the UPDATE, now relates to the sub-query results, the correlation. The work around is to make "big but simpler" sub-query and join to that.

SQL Subquery using IN Statment with coalesce

I have the following SELECT statmentment
SELECT
UserID
,UserName
,TradingParty
,Email
,[PrivDesc]
,LastLogin
,IsApproved
FROM
cte_getAll allUsers
WHERE
allUsers.TradingParty = COALESCE(#TradingParty, allUsers.TradingParty)
AND allUsers.Username = COALESCE(#Username, allUsers.Username)
AND allUsers.Email = COALESCE(#EmailAddress, allUsers.Email)
AND DATEADD(dd, DATEDIFF(dd, 0, allUsers.[LastLogin]), 0) >= COALESCE(#FromDate, DATEADD(dd, DATEDIFF(dd, 0, allUsers.[LastLogin]), 0))
AND DATEADD(dd, DATEDIFF(dd, 0, allUsers.[LastLogin]), 0) <= COALESCE( #ToDate, DATEADD(dd, DATEDIFF(dd, 0, allUsers.[LastLogin]), 0))
AND allUsers.IsApproved = COALESCE(#AccountActive, allUsers.IsApproved)
AND allUsers.[PrivId] -- IN (SELECT privId from #selectedPriv)
IN (COALESCE((SELECT PrivID FROM #selectedPriv), allUsers.[PrivId]))
EDIT
Prior to this statment i am populating the #selectedPriv temp table according to the users input. If there is not user input therefore the table will contain nothin
On the final AND statement i am trying to find all data where privId is equal to a list of privs which the user has entered. So for example the user eneters 1,2,3,4,5,6 that is stored into a temp table, from this i need to find all the rows from my original table which are associated with these priv.
Here is my issue if i use the commented IN statement it works but since the user is allowed to pass in NULL i need it within a COALESCE, but when i do this i get the message
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression.
I havent got a clue on why this is. Any ideas that will help me fix this issue?
If I understand your question correctly, you have a table variable that has values that you want to select from, but if they don't have any values in the table, you don't want the restriction at all.
The reason you're getting the error you're getting is due to COALESCE() only expecting a single value to transform, but your query is returning multiple.
This may be what you're looking for:
AND
(
NOT EXISTS (SELECT * FROM #selectedPriv WHERE PrivID IS NOT NULL)
OR
(
EXISTS (SELECT * FROM #selectedPriv WHERE PrivID IS NOT NULL)
AND allUsers.[PrivId] IN (SELECT PrivID FROM #selectedPriv)
)
)
Since you are populating the temp table #selectedPriv prior to this statement just add an else there -- if the input is null have #selectedPriv =
SELECT DISTINCT PrivId FROM cte_getAll
This should be faster than a more complicated where statement that checks count(*) in #selectedPriv which is the other way to do it.
COALESCE can only take one value for it's first argument, which is why it complains when you get more than one value from that query. You could switch that part for something a bit different using some ANDs and ORs. (Note: untested, but should at least be close.)
AND (((select count(*) from #selectedPriv) = 0)
OR ((select count(*) from #selectedPriv) != 0 AND allUsers.[PrivId] IN (SELECT privId from #selectedPriv)))
coalesce works fine but you can use ORs instead and that might help you with your last AND.
SELECT
UserID,
UserName,
TradingParty,
Email,
[PrivDesc],
LastLogin,
IsApproved
FROM
cte_getAll allUsers
WHERE
allUsers.TradingParty = COALESCE(#TradingParty,allUsers.TradingParty)
AND (#Username IS NULL OR allUsers.Username = #Username)
AND (#EmailAddress IS NULL OR allUsers.Email = #EmailAddress)
AND (#FromDate IS NULL OR DATEADD(dd,DATEDIFF(dd,0,allUsers.[LastLogin]),0) >= #FromDate)
AND (#ToDate IS NULL OR DATEADD(dd,DATEDIFF(dd,0,allUsers.[LastLogin]),0) <= #ToDate)
AND (#AccountActive IS NULL OR allUsers.IsApproved = #AccountActive)
AND (#PrivIDS IS NULL OR allUsers.[PrivId] IN (SELECT PrivID FROM #selectedPriv))

SQL Subquery returned more than 1 value

My query causes the following error:
Msg 512, Level 16, State 1, Procedure Item_insupd, Line 17
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Query:
INSERT INTO [Total_Database].[dbo].[Item]
(
ItemID,
ItemNo,
ItemDescription,
Notes,
StandardCost,
SalesGLAccountID,
ItemTypeID,
Backorderable
)
(
SELECT [nr],
[nr],
[Latijn]+' '+[Subgroep]+' '+CAST([nr] as VARCHAR(255)),
[NL]+' '+[Vorm]+' '+[Kenmerk]+' '+[Hoogte],[Inkoopprijs],
(4),
(case when [Productgroep]='PB' then 1 else 5 end),
(1)
FROM [ACCESDATA].[dbo].[Planten]
);
I suspect this to happen because my subquery does not contain a WHERE, unfortunately I do not know how to construct a correct WHERE clause.
I suspect the problem is in this string (line 26 in your code):
IF NOT (EXISTS (SELECT G.GLAccountID FROM GLAccnt G INNER JOIN Inserted I ON G.GLAccountID = I.SalesGLAccountID))
OR ((SELECT I.COGSGLAccountID FROM Inserted I) IS NOT NULL) AND NOT (EXISTS (SELECT G.GLAccountID FROM GLAccnt G INNER JOIN Inserted I ON G.GLAccountID = I.COGSGLAccountID))
It looks like (SELECT I.COGSGLAccountID FROM Inserted I) return more than one row, so you're getting an error.
You're treating inserted as a one row table (for example, you're getting parameters from it like SELECT #ItemNo = I.ItemNo, #ItemDescription = I.ItemDescription FROM Inserted I, but inserted table can have more than one row. So in your case I think you have 3 options - check that there's only 1 row in inserted, rewrite trigger as set-based, or use cursor.
Here's sql fiddle with somewhat similar example.
If you really only want to insert one row, then You just add Where at the end, followed by some predicate (logical statement) that will be true for only one row in the table the query is reading from.
INSERT INTO [Total_Database].[dbo].[Item](ItemID,
ItemNo,ItemDescription,Notes,StandardCost,SalesGLAccountID,
ItemTypeID,Backorderable)
SELECT [nr],[nr],[Latijn]+' '+[Subgroep]+' '+CAST([nr] as VARCHAR(255)),
[NL]+' '+[Vorm]+' '+[Kenmerk]+' '+[Hoogte],[Inkoopprijs],(4),
(case when [Productgroep]='PB' then 1 else 5 end),(1)
FROM [ACCESDATA].[dbo].[Planten]
Where [SomeColumnName] = [some Value];
... but when performing an Insert using a select to generate the rows to be inserted, you just type the Select statement instead of the Values() clause, without surrounding parentheses. I think that because you had the surrounding parentheses, the query processor assumed you wanted that to be a single value. Do you want to only insert one row of data? or a whole set of data rows ?
INSERT INTO [Total_Database].[dbo].[Item]
(
ItemID,
ItemNo,
ItemDescription,
Notes,
StandardCost,
SalesGLAccountID,
ItemTypeID,
Backorderable
) IN
(
SELECT [nr],
[nr],
[Latijn]+' '+[Subgroep]+' '+CAST([nr] as VARCHAR(255)),
[NL]+' '+[Vorm]+' '+[Kenmerk]+' '+[Hoogte],[Inkoopprijs],
(4),
(case when [Productgroep]='PB' then 1 else 5 end),
(1)
FROM [ACCESDATA].[dbo].[Planten]
);

How to insert bulky value to sql table?

I want to add bulky data from another data below. But I can not do that: error is returned. But areas are the same as another.
declare #hrmtable1 table(musterino int, ekno smallint)
insert into #hrmtable1 (musterino , ekno)
select distinct musterino, ekno
from hareketmuhasebe (nolock)
where islemtarihi >= '20120101'
and isnull(musterino, 0) <> 0
and isnull(musterino, 0) > 9000000
and isnull(ekno,0) <> 0
insert into table1(A,B,C,D,E,. . . . .N)
SELECT DISTINCT
case when ((select count(*) from table1 where musterino=e.musterino) > 0)
then (select top 1 *
from dbo.table1
where musterino = e.musterino
order by ekno desc)
else
(select 100, e.musterino, e.ekno, 0, K, L, M)
from #hrmtable1 e )
end
ERROR:
Msg 120, Level 15, State 1, Line 10
The select list for the INSERT statement contains fewer items than the insert list.
The number of SELECT values must match the number of INSERT columns.
As mentioned in the error the number of columns in insert does not mach the number of value that you are providing
insert into #hrmtable1 (musterino , ekno)
select distinct musterino,ekno
from hareketmuhasebe (nolock)
where islemtarihi >= '20120101'
and isnull(musterino,0) <> 0 and isnull(musterino,0) < 9000000 and isnull(ekno,0) <> 0
Try this:
insert into #hrmtable1 (musterino , ekno)
select distinct musterino,ekno
from hareketmuhasebe (nolock)
where islemtarihi >= '20120101'
and isnull(musterino,0) <> 0 and isnull(musterino,0) < 9000000 and isnull(ekno,0) <> 0
You are having 2 columns in insert & 5 columns in select clause, that is the cause of error.
EDIT: Since you edited the question, still the answer remains the same. Your number of columns in Select statement doesn't match to your insert statement columns in the 2nd part of your code.
In your first statement you are specifying 2 columns and in select you have 5 columns, they should match and that is what the error is telling you exactly.
insert into #hrmtable1 (musterino , ekno)
^^^^^^^ ^^^^
select distinct musterino,ekno,defterid,dovizcinsi, subekodu
^^^^^^^ ^^^ ^^^^ ^^^^^ ^^^^^
From your insert statement it looks like you don't need the last three columns in your Select statement.
The select list for the INSERT statement contains fewer items than the
insert list. The number of SELECT values must match the number of
INSERT columns.
The error itself tells you the story that what you are doing wrong. you have fewer columns in insert statement than to select statement.
From MSDN
The select list of the subquery must match the column list of the
INSERT statement. If no column list is specified, the select list must
match the columns in the table or view being inserted into.
Read more about Inert into

Performing a prefix computation using SQL without defined procedures

I have a table with a column of integers - I need a way to generate the "prefix" of this column in another table.
For e.g.
I have 1, 0, 0, 0, 1, 0, 1, 0, 0 as the input
I need 1, 1, 1, 1, 2, 2, 3, 3, 3 as the output
This needs to be done in SQLite's SQL dialect , no user defined functions or stored procedures are possible.
try something like this:
select value,
(select sum(t2.value) from table t2 where t2.id <= t1.id ) as accumulated
from table t1
from: SQLite: accumulator (sum) column in a SELECT statement
So to insert from input table to output table you need following query:
INSERT INTO output
SELECT id,
(SELECT sum(i1.value) FROM input AS i1 WHERE i1.rowid <= i2.rowid) as VALUE
FROM input AS i2