Related
I have a table of 811 records. I want to get five records at a time and assign it to variable. Next time when I run the foreach loop task in SSIS, it will loop another five records and overwrite the variable. I have tried doing with cursor but couldn't find the solution. Any help will be highly appreciated. I have table like this for e.g.
ServerId ServerName
1 Abc11
2 Cde22
3 Fgh33
4 Ijk44
5 Lmn55
6 Opq66
7 Rst77
. .
. .
. .
I want query should take first five names as follows and assign it to variable
ServerId ServerName
1 Abc11
2 Cde22
3 Fgh33
4 Ijk44
5 Lmn55
Then next loop takes another five name and overwrite the variable value and so on till the last record is consumed.
Taking ltn's answer into consideration this is how you can achieve limiting the rows in SSIS.
The Design will look like
Step 1 : Create the variables
Name DataType
Count int
Initial int
Final int
Step 2 : For the 1st Execute SQL Task write the sql to store the count
Select count(*) from YourTable
In the General tab of this task Select the ResultSet as Single Row.
In the ResultSet tab map the result to the variable
ResultName VariableName
0 User::Count
Step 3 : In the For Loop container enter the expression as shown below
Step 4 : Inside the For Loop drag an Execute SQL Task and write the expression
In Parameter Mapping map the initial variable
VariableName Direction DataType ParameterName ParameterSize
User::Initial Input NUMERIC 0 -1
Result Set tab
Result Name Variable Name
0 User::Final
Inside the DFT u can write the sqL to get the particular rows
Click on Parameters and select the variable INITIAL and FINAL
if your data will not be update between paging cycles and the sort order is always the same then you could try an approach similiar to:
CREATE PROCEDURE TEST
(
#StartNumber INT,
#TakeNumber INT
)
AS
SELECT TOP(#TakeNumber)
*
FROM(
SELECT
RowNumber=ROW_NUMBER() OVER(ORDER BY IDField DESC),
NameField
FROM
TableName
)AS X
WHERE RowNumber>=#StartNumber
We have an Oracle based system that manages devices and stores their details and configuration in a table called "configs". Each device is made up of several modules and the configuration of each module is saved as a comma-separated string. For example:
device_id module values
1 1 3,4,2,3
1 2 4,1,3,4
1 3 2,1,2,3
1 4 6,4,2,1
1 5 1,4,2,3
1 6 1,3,4,4
2 1 3,4,2,3
2 2 4,1,3,4
2 3 2,3,2,3
2 4 6,4,2,1
2 5 1,8,2,3
2 6 1,3,4,4
3 1 3,4,2,3
3 2 4,1,3,4
3 3 2,1,2,3
3 4 6,4,2,1
3 5 1,4,2,3
3 6 1,3,4,4
4 1 3,4,2,3
4 2 4,1,3,4
4 3 2,1,2,4
4 4 6,4,2,1
4 5 1,4,2,3
4 6 1,3,7,4
I need to audit the system and identify each module whose configuration does not match a known good config. Ideally, I want to run a query like this, assuming the config for device 1 is my good config:
select device_id,module
from configs
where values != (select values from configs where device_id = 1)
But that returns an error:
ORA-01427: single-row subquery returns more than one row
If I change the query to this, it works:
select device_id,module
from configs
where values = (select values from configs where device_id = 1 and module = 1);
But then I have to run the query for each value of "module".
What I'd like to do is write a query that will allow me to do this in one go. It's been hinted that I could use a cursor statement but I've struggled to find an "oracle cursors for dummies" type article and nothing I've looked at has helped me so far, including http://docs.oracle.com/cd/B28359_01/server.111/b28286/expressions006.htm#SQLRF52057. Can anyone suggest something?
Thanks.
Does the module numbers have to match ? i.e. is the configuration of the module 2 (of the device 1) considered as a good configuration for the module 3 (of some other device)
If so, there are several good configuration (that's why the db says single-row subquery returns more than one row). You have to account for that :
select device_id, module
from configs
where values not in (select values from configs where device_id = 1)
If not, you have to choose the one matching the considered row, for example :
select device_id, module
from configs c1
where values = (
select values
from configs c2
where device_id = 1
and c1.module = c2.module
)
Your query that is producing errors is attempting to compare a list of items in a single value context. You need to change your "!=" to "not in" and it should work. Here is the adjusted query:
select device_id, module
from configs
where values not in (select values from configs where device_id = 1)
If I understood you right, I suppose you can use something like this:
DECLARE
device_string VARCHAR2 (100);
BEGIN
FOR i IN (SELECT * FROM configs WHERE device_id = 1)
LOOP
SELECT listagg(device_id, ';')
WITHIN GROUP (ORDER BY device_id)
INTO device_string
FROM configs
WHERE values != i.values AND module=i.module;
DBMS_OUTPUT.PUT_LINE(
' Bad config for module ' || i.module ||
' in devices: ' || device_string);
END LOOP;
END;
I have the following structure
construction
id
1
building-step
id construction_id step_id worker_id
1 1 1 1
1 1 2 2
step
id name
1 foundation
2 wall
3 roof
When a new construction is added using a template, building-steps are generated. After the initial configuration steps can be added or removed.
One of the requirements is to display the construction template as a string. The template is dynamic because you can add and remove steps.
In this case the template name is "foundation+wall". If I add another building-step the template name will be "foundation+wall+roof".
My question is, how can this be done in optimized way?
Is the SQL structure the problem for this dynamic complexity?
In Postgres specifically you can use the string_agg function, which concats rows of strings.
In you example, you could try:
select string_agg(nm,'+') from(
select st.name as nm
from building-step bs
inner join
step st
on bs.step_id=st.id
where bs.construction_id=1
order by bs ASC
); --done by hand, may have small errors
It will support edits in both tables anytime, and will perform nicely.
I have table test( ID Numeric(11,0), report varchar(255) )
and data looks below
1 ,Age,,,,,,family_status,,,,,,
2 ,,,,,,,,retaliation,hostile environment,,,,
3 ,,,,,,,,,,,,,
4 ,,,,,,,,retaliation,,,,,
5 ,,,,,,,,,hostile environment,,,,
6 ,Age,,,,,,,,,,,,
7 ,,,,national_origin,,,,,,,,,
8 Sex,,,,,,,,,,,,,
9 ,,,,national_origin,,disability,,retaliation,,,,,
10 Sex,,,,,,,,retaliation,,,,,
11 ,,,,,,,,
and i would like to update this table by replacing or using any other data scribing to remove extra commas so that data looks
1 Age,family_status
2 retaliation,hostile environment
3
4 retaliation
5 hostile environment
6 Age
7 national_origin,
8 Sex
9 national_origin,disability,retaliation
10 Sex,retaliation
11
i try to use the below statement but not sure how to loop through so that it will check and remove all the commas
UPDATE table test SET report = replace(report , ',,', ',')
If you are just doing this as a one off task (rather than a scripted process you expect to use repeatedly) you could always just run this query repeatedly until you get 0 rows updated
UPDATE table test SET report = replace(report , ',,', ',')
WHERE report like '%,,%'
If you need to do this over and over, or put it in a program I recommend using your procedural (non SQL code) to do the replace where you have better text manipulation commands.
If you aren't thrilled with that, check out this blog article I wrote on a similar problem of replacing repeating spaces from a string.
I have the following tables, the groups table which contains hierarchically ordered groups and group_member which stores which groups a user belongs to.
groups
---------
id
parent_id
name
group_member
---------
id
group_id
user_id
ID PARENT_ID NAME
---------------------------
1 NULL Cerebra
2 1 CATS
3 2 CATS 2.0
4 1 Cerepedia
5 4 Cerepedia 2.0
6 1 CMS
ID GROUP_ID USER_ID
---------------------------
1 1 3
2 1 4
3 1 5
4 2 7
5 2 6
6 4 6
7 5 12
8 4 9
9 1 10
I want to retrieve the visible groups for a given user. That it is to say groups a user belongs to and children of these groups. For example, with the above data:
USER VISIBLE_GROUPS
9 4, 5
3 1,2,4,5,6
12 5
I am getting these values using recursion and several database queries. But I would like to know if it is possible to do this with a single SQL query to improve my app performance. I am using MySQL.
Two things come to mind:
1 - You can repeatedly outer-join the table to itself to recursively walk up your tree, as in:
SELECT *
FROM
MY_GROUPS MG1
,MY_GROUPS MG2
,MY_GROUPS MG3
,MY_GROUPS MG4
,MY_GROUPS MG5
,MY_GROUP_MEMBERS MGM
WHERE MG1.PARENT_ID = MG2.UNIQID (+)
AND MG1.UNIQID = MGM.GROUP_ID (+)
AND MG2.PARENT_ID = MG3.UNIQID (+)
AND MG3.PARENT_ID = MG4.UNIQID (+)
AND MG4.PARENT_ID = MG5.UNIQID (+)
AND MGM.USER_ID = 9
That's gonna give you results like this:
UNIQID PARENT_ID NAME UNIQID_1 PARENT_ID_1 NAME_1 UNIQID_2 PARENT_ID_2 NAME_2 UNIQID_3 PARENT_ID_3 NAME_3 UNIQID_4 PARENT_ID_4 NAME_4 UNIQID_5 GROUP_ID USER_ID
4 2 Cerepedia 2 1 CATS 1 null Cerebra null null null null null null 8 4 9
The limit here is that you must add a new join for each "level" you want to walk up the tree. If your tree has less than, say, 20 levels, then you could probably get away with it by creating a view that showed 20 levels from every user.
2 - The only other approach that I know of is to create a recursive database function, and call that from code. You'll still have some lookup overhead that way (i.e., your # of queries will still be equal to the # of levels you are walking on the tree), but overall it should be faster since it's all taking place within the database.
I'm not sure about MySql, but in Oracle, such a function would be similar to this one (you'll have to change the table and field names; I'm just copying something I did in the past):
CREATE OR REPLACE FUNCTION GoUpLevel(WO_ID INTEGER, UPLEVEL INTEGER) RETURN INTEGER
IS
BEGIN
DECLARE
iResult INTEGER;
iParent INTEGER;
BEGIN
IF UPLEVEL <= 0 THEN
iResult := WO_ID;
ELSE
SELECT PARENT_ID
INTO iParent
FROM WOTREE
WHERE ID = WO_ID;
iResult := GoUpLevel(iParent,UPLEVEL-1); --recursive
END;
RETURN iResult;
EXCEPTION WHEN NO_DATA_FOUND THEN
RETURN NULL;
END;
END GoUpLevel;
/
Joe Cleko's books "SQL for Smarties" and "Trees and Hierarchies in SQL for Smarties" describe methods that avoid recursion entirely, by using nested sets. That complicates the updating, but makes other queries (that would normally need recursion) comparatively straightforward. There are some examples in this article written by Joe back in 1996.
I don't think that this can be accomplished without using recursion. You can accomplish it with with a single stored procedure using mySQL, but recursion is not allowed in stored procedures by default. This article has information about how to enable recursion. I'm not certain about how much impact this would have on performance verses the multiple query approach. mySQL may do some optimization of stored procedures, but otherwise I would expect the performance to be similar.
Didn't know if you had a Users table, so I get the list via the User_ID's stored in the Group_Member table...
SELECT GroupUsers.User_ID,
(
SELECT
STUFF((SELECT ',' +
Cast(Group_ID As Varchar(10))
FROM Group_Member Member (nolock)
WHERE Member.User_ID=GroupUsers.User_ID
FOR XML PATH('')),1,1,'')
) As Groups
FROM (SELECT User_ID FROM Group_Member GROUP BY User_ID) GroupUsers
That returns:
User_ID Groups
3 1
4 1
5 1
6 2,4
7 2
9 4
10 1
12 5
Which seems right according to the data in your table. But doesn't match up with your expected value list (e.g. User 9 is only in one group in your table data but you show it in the results as belonging to two)
EDIT: Dang. Just noticed that you're using MySQL. My solution was for SQL Server. Sorry.
-- Kevin Fairchild
There was already similar question raised.
Here is my answer (a bit edited):
I am not sure I understand correctly your question, but this could work My take on trees in SQL.
Linked post described method of storing tree in database -- PostgreSQL in that case -- but the method is clear enough, so it can be adopted easily for any database.
With this method you can easy update all the nodes depend on modified node K with about N simple SELECTs queries where N is distance of K from root node.
Good Luck!
I don't remember which SO question I found the link under, but this article on sitepoint.com (second page) shows another way of storing hierarchical trees in a table that makes it easy to find all child nodes, or the path to the top, things like that. Good explanation with example code.
PS. Newish to StackOverflow, is the above ok as an answer, or should it really have been a comment on the question since it's just a pointer to a different solution (not exactly answering the question itself)?
There's no way to do this in the SQL standard, but you can usually find vendor-specific extensions, e.g., CONNECT BY in Oracle.
UPDATE: As the comments point out, this was added in SQL 99.