I am trying to create a column that contains counts, but the problem is where I go to reuse the subquery that does this the temporary table created previously becomes unavailable as it no longer exists.
My question is how can I store the result of a previous subquery so I can run something on that result later on in the same query?
First for the counts I have:
CREATE TEMPORARY TABLE _temp_unique_entity_manufacturers
(
entityId INT(11),
manufacturerRef INT(11),
manufacturerName VARCHAR(255),
KEY(entityId),
KEY(manufacturerRef)
)
ENGINE=MEMORY AS
(SELECT DISTINCT entityRef AS entityId, manufacturer AS manufacturerRef, pm.name AS manufacturerName FROM enquiries, parts_trading, parts_manufacturers AS pm WHERE manufacturer = pm.id AND enquiryRef = enquiries.id)
And then in my main query I work with this table, specifically this part:
IF((SELECT COUNT(*) FROM _temp_unique_entity_manufacturers WHERE entityId = eo.id) > 0,
(SELECT COUNT(*) FROM _temp_unique_entity_manufacturers WHERE entityId = eo.id),
0
) AS manufacturers
The second subquery fails because the temp table is gone at this point. Is there a way where I dont have to write out the same subquery again and again?
case when
((SELECT COUNT(*) FROM _temp_unique_entity_manufacturers WHERE entityId = eo.id) > 0) then
(SELECT COUNT(*) FROM _temp_unique_entity_manufacturers WHERE entityId = eo.id) else
0 end
) AS manufacturers
--------------
ex:
select coname,(case when cond then result else second result end) as user_colname from
tablename
----------------------
If condition implement in sql as case when statement
Related
update customers
set transaction_id = (
select transaction_id from transactions
where transaction_type IN (select transaction_type from customers where id = 1)
);
gives the error 1093. You can't specify target table for update in where clause? Anyone know why I am not allowed to use this Subquery?
error 1093 comes from mysql, so i think you misstagged it.
But basically you need to create a subquery, so the database, doesn't use customers, which you are trying to change.
You must be sure that the subquery only reuturns one scalar value
CREATE tABLe customers (id int , transaction_id int)
CREATE tABLE transactions (transaction_id int,transaction_type int)
update customers
set transaction_id = (
select transaction_id from transactions
where transaction_type IN (select transaction_type from (SELECT transaction_type FROM customers where id = 10) c )
);
Rows matched: 0 Changed: 0 Warnings: 0
fiddle
I'm trying to build a stored procedure that transforms a lot of data from a very condensed table with a key to find any given information, to a wide table with all of the information in columns per group. This is to preprocess information and alleviate at point of use. I've structured my query like below.
Select distinct a.group_,
, (select value from mytable b where a.group = b.group) as Information 1
from mytable a
However, when I want to use a case statement, it breaks the reference to the outer query
Select distinct a.group_,
, (case
when (select value from mytable b where a.group = b.group) is not null -- this breaks
then (select value from mytable b where a.group = b.group)
else (select anothervalue from mytable b where a.group = b.group)
end ) as Information 1
from mytable a
I thought about a work around with a simple case to find if the value is null, and execute an else statement, but I found that my 'is not null' didn't work in the when statment, and I needed to reference the outer query anyways for the else. So ultimately, I need some method to be able to conditionally select values for one column and have it tied to the group that I'm trying to transform. Any help would be appreciated, thanks.
Edit:
Below is an example. To clarify, I need to be able to conditionally select information from potentially multiple sources together into the same column for any given group. It's also going to be working on a large amount of data so I need it to be as minimally computationally intensive as possible. From this table, I will combine all of these groups in different combinations to have one line per collection of groups, with each group at least one column in the final table. It's a little more complicated than that, but that's the general idea.
if OBJECT_ID(N'tempdb..#tt1') is not null
drop table #tt1
declare #counter INT
set #counter = 1
create table #tt1 (group_ int, id1 int, id2 int, info varchar(10))
while (#counter <= 5)
begin
insert into #tt1 (group_, id1, id2, info)
select #counter, #counter, #counter, CONCAT('info ', cast(#counter as varchar(10)))
set #counter = #counter +1
end
set #counter = 1
while (#counter <= 5)
begin
insert into #tt1 (group_, id1, id2, info)
select #counter, #counter, #counter+1, CONCAT('info ', cast(#counter+5 as varchar(10)))
set #counter = #counter +1
end
select distinct a.group_,
(select info from #tt1 b where a.group_ = b.group_ and id1 = 1 and id2=2) as Group1Info6
from #tt1 a
--The above works fine
select distinct a.group_,
(case
when (select info from #tt1 b where A.group_ = b.group_ and id1=1 and id2 =2) is < 6
then (select info from #tt1 b where A.group_ = b.group_ and id1=1 and id2 =2)
else (select info from #tt1 b where A.group_ = b.group_ and id1=1 and id2=1)
end) as Group1info
from #tt1 a
--The above does not.
Edit2:
My desired results would look something like this. In my actual data there are many group 1's, with many group 1 info columns.
group_
Group1Info
Group2Info
Group3Info
Group4Info
Group5Info
1
info
2
info
3
info
4
info
5
info
Then I'll present the information more cleanly to the end user like this.
group_
Group1Info
Group2Info
Group3Info
Group4Info
Group5Info
1-5
info
info
info
info
info
Is there a way to rewrite this query without getting error?: Subquery returned more than 1 value.
This is query is used in a LEFT JOIN in a table-valued function. Per requirement, I need to by default pull two scenario IDs (if parameter value is NULL or empty)
DECLARE #pScenarioName AS VARCHAR(30)
select
externalID,
PropertyAssetId,
LeaseID,
BeginDate
from ae11.dbo.ivw_Leases
WHERE PropertyAssetID IN
(select ID from AE11.dbo.PropertyAssets where scenarioID IN
(CASE WHEN isnull(#pScenarioName, '') = ''
THEN (select top 2 ID from rvw_Scenarios where Name like '[0-9][0-9][0-9][0-9]%'
AND LEN(Name) = 8
order by Name desc)
ELSE
(select ID from aex.dbo.rvw_Scenarios
where [Name] IN (#pScenarioName))
END)
)
I haven't tested this, but I use a similar approach when dealing with parameters. Of course, this won't necessarily work if the order of the ID is crucial in your second subquery.
SELECT ExternalID
,PropertyAssetId
,LeaseID
,BeginDate
FROM ae11.dbo.ivw_Leases
WHERE PropertyAssetID IN
(SELECT ID
FROM AE11.dbo.PropertyAssets
WHERE scenarioID IN
(SELECT TOP 2 ID
FROM rvw_Scenarios
WHERE (#ISNULL(#pScenarioName,'') = ''
AND Name LIKE '[0-9][0-9][0-9][0-9]%'
AND LEN(Name) = 8)
ORDER BY Name DESC
UNION ALL
SELECT ID FROM aex.dbo.rvw_Scenarios
WHERE (#pScenarioName IS NOT NULL)
AND [Name] IN (#pScenarioName)))
I have a table that contains two columns
ID | Name
----------------
1 | John
2 | Sam
3 | Peter
6 | Mike
It has missed IDs. In this case these are 4 and 5.
How do I find and insert them together with random names into this table?
Update: cursors and temp tables are not allowed. The random name should be 'Name_'+ some random number. Maybe it would be the specified value like 'Abby'. So it doesn't matter.
Using a recursive CTE you can determine the missing IDs as follows
DECLARE #Table TABLE(
ID INT,
Name VARCHAR(10)
)
INSERT INTO #Table VALUES (1, 'John'),(2, 'Sam'),(3,'Peter'),(6, 'Mike')
DECLARE #StartID INT,
#EndID INT
SELECT #StartID = MIN(ID),
#EndID = MAX(ID)
FROM #Table
;WITH IDS AS (
SELECT #StartID IDEntry
UNION ALL
SELECT IDEntry + 1
FROM IDS
WHERE IDEntry + 1 <= #EndID
)
SELECT IDS.IDEntry [ID]
FROM IDS LEFT JOIN
#Table t ON IDS.IDEntry = t.ID
WHERE t.ID IS NULL
OPTION (MAXRECURSION 0)
The option MAXRECURSION 0 will allow the code to avoid the recursion limit of SQL SERVER
From Query Hints and WITH common_table_expression (Transact-SQL)
MAXRECURSION number Specifies the maximum number of recursions
allowed for this query. number is a nonnegative integer between 0 and
32767. When 0 is specified, no limit is applied. If this option is not specified, the default limit for the server is 100.
When the specified or default number for MAXRECURSION limit is reached
during query execution, the query is ended and an error is returned.
Because of this error, all effects of the statement are rolled back.
If the statement is a SELECT statement, partial results or no results
may be returned. Any partial results returned may not include all rows
on recursion levels beyond the specified maximum recursion level.
Generating the RANDOM names will largly be affected by the requirements of such a name, and the column type of such a name. What exactly does this random name entail?
You can do this using a recursive Common Table Expression CTE. Here's an example how:
DECLARE #MaxId INT
SELECT #MaxId = MAX(ID) from MyTable
;WITH Numbers(Number) AS
(
SELECT 1
UNION ALL
SELECT Number + 1 FROM Numbers WHERE Number < #MaxId
)
SELECT n.Number, 'Random Name'
FROM Numbers n
LEFT OUTER JOIN MyTable t ON n.Number=t.ID
WHERE t.ID IS NULL
Here are a couple of articles about CTEs that will be helpful to Using Common Table Expressions and Recursive Queries Using Common Table Expressions
Start by selecting the highest number in the table (select top 1 id desc), or select max(id), then run a while loop to iterate from 1...max.
See this article about looping.
For each iteration, see if the row exists, and if not, insert into table, with that ID.
I think recursive CTE is a better solution, because it's going to be faster, but here is what worked for me:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[TestTable]') AND type in (N'U'))
DROP TABLE [dbo].[TestTable]
GO
CREATE TABLE [dbo].[TestTable](
[Id] [int] NOT NULL,
[Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_TestTable] PRIMARY KEY CLUSTERED
(
[Id] ASC
))
GO
INSERT INTO [dbo].[TestTable]([Id],[Name]) VALUES (1, 'John')
INSERT INTO [dbo].[TestTable]([Id],[Name]) VALUES (2, 'Sam')
INSERT INTO [dbo].[TestTable]([Id],[Name]) VALUES (3, 'Peter')
INSERT INTO [dbo].[TestTable]([Id],[Name]) VALUES (6, 'Mike')
GO
declare #mod int
select #mod = MAX(number)+1 from master..spt_values where [type] = 'P'
INSERT INTO [dbo].[TestTable]
SELECT y.Id,'Name_' + cast(newid() as varchar(45)) Name from
(
SELECT TOP (select MAX(Id) from [dbo].[TestTable]) x.Id from
(
SELECT
t1.number*#mod + t2.number Id
FROM master..spt_values t1
CROSS JOIN master..spt_values t2
WHERE t1.[type] = 'P' and t2.[type] = 'P'
) x
WHERE x.Id > 0
ORDER BY x.Id
) y
LEFT JOIN [dbo].[TestTable] on [TestTable].Id = y.Id
where [TestTable].Id IS NULL
GO
select * from [dbo].[TestTable]
order by Id
GO
http://www.sqlfiddle.com/#!3/46c7b/18
It's actually very simple :
Create a table called #All_numbers which should contain all the natural number in the range that you are looking for.
#list is a table containing your data
select a.num as missing_number ,
'Random_Name' + convert(varchar, a.num)
from #All_numbers a left outer join #list l on a.num = l.Id
where l.id is null
I have a record in my table like
memberId PersonId Year
4057 1787 2
4502 1787 3
I want a result from a query like this
memberId1 MemberId2 PersonId
4057 4502 1787
How to write a query ??
Don't do this in a query, do it in the application layer.
Don't do this in SQL. At best you can try:
SELECT table1.memberId memberId1, table2.memberId MemberId2, PersonId
FROM table table1 JOIN table table2 USING (PersonId)
But it won't do what you expect if you have more than 2 Members for a person. (It will return every possible combination.)
Below an example on how to do it directly in SQL. Mind that there is plenty of room for optimisation but this version should be rather fast, esp if you have an index on PersonID and year.
SELECT DISTINCT PersonID,
memberId1 = Convert(int, NULL),
memberId2 = Convert(int, NULL)
INTO #result
FROM myTable
WHERE Year IN (2 , 3)
CREATE UNIQUE CLUSTERED INDEX uq0_result ON #result (PersonID)
UPDATE #result
SET memberId1 = t.memberId
FROM #result upd
JOIN myTable t
ON t.PersionId = upd.PersonID
AND t.Year = 2
UPDATE #result
SET memberId2 = t.memberId
FROM #result upd
JOIN myTable t
ON t.PersionId = upd.PersonID
AND t.Year = 3
SELECT * FROM #result
if you want all member ids for each person_id, you could use [for xml path] statement (great functionality)
to concat all memberId s in a string
select distinct PersonId
, (select ' '+cast(t0.MemberId as varchar)
from table t0
where t0.PersonId=t1.PersonId
for xml path('')
) [Member Ids]
from table t1
resulting in:
PersonId Members Ids
1787 ' 4057 4502'
if you really need seperate columns, with unlimited number of memberIds, consider using
a PIVOT table, but far more complex to use