Related
I'm having two tables namely ds_message and ds_params, the first table contains the template and the second tables contains the key value pair
Table Structure: ds_message
_____________________________________________
id template
_____________________________________________
1 'Dear {a}, the price of {b} is {c}'
2 'Dear {i}, you selected the product {j}'
Schema:
CREATE TABLE `ds_message` (
`id` int NOT NULL,
`template` varchar(500) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='';
ALTER TABLE `ds_message`
ADD PRIMARY KEY (`id`);
INSERT INTO `ds_message` (`id`, `template`) VALUES
(1, 'Dear {a}, the price of {b} is {c}');
INSERT INTO `ds_message` (`id`, `template`) VALUES
(2, 'Dear {i}, you selected the product {j}');
Table Structure: ds_params
_________________________________________________
id message_id json_key json_value
_________________________________________________
1 1 a John
2 1 b bat
3 1 c $10
4 2 i Emma
5 2 j Jam
Schema:
CREATE TABLE `ds_params` (
`id` int NOT NULL,
`message_id` int NOT NULL,
`json_key` varchar(500) NOT NULL,
`json_value` varchar(500) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='';
ALTER TABLE `ds_params`
ADD PRIMARY KEY (`id`);
INSERT INTO `ds_params` (`id`, `message_id`, `json_key`, `json_value`) VALUES
(1, 1, 'a', 'John');
INSERT INTO `ds_params` (`id`, `message_id`, `json_key`, `json_value`) VALUES
(2, 1, 'b', 'bat');
INSERT INTO `ds_params` (`id`, `message_id`, `json_key`, `json_value`) VALUES
(3, 1, 'c', '$10');
INSERT INTO `ds_params` (`id`, `message_id`, `json_key`, `json_value`) VALUES
(4, 2, 'i', 'Emma');
INSERT INTO `ds_params` (`id`, `message_id`, `json_key`, `json_value`) VALUES
(5, 2, 'j', 'Jam');
I need to replace the keys (for example {a} => John) in the ds_message table.
I tried the following code,
UPDATE ds_message AS t
INNER JOIN ds_params m ON m.message_id = t.id
SET t.template = REPLACE(t.template, CONCAT('{', m.json_key , '}'), m.json_value);
Once I executed the code I'm getting the output like this, only the first key gets replaced, remaining keys not get update.
_____________________________________________
id template
_____________________________________________
1 Dear John, the price of {b} is {c}
2 Dear Emma, you selected the product {j}
Kindly assist me how to do this.
We have 2 options.
First is using while loop.
SET #n = 0;
SELECT COUNT(*) FROM ds_params INTO #n;
SET #i=0;
WHILE #i<#n DO
UPDATE ds_message AS t
INNER JOIN ds_params m ON m.message_id = t.id AND m.id = #i
SET t.template = REPLACE(t.template, CONCAT('{', m.json_key , '}'), m.json_value)
SET #i = #i + 1;
END WHILE;
2nd Option is this. If you have a fix json_key
UPDATE ds_message AS t
LEFT JOIN ds_params a ON a.message_id = t.id and a.json_key='a'
LEFT JOIN ds_params b ON b.message_id = t.id and b.json_key='b'
LEFT JOIN ds_params c ON c.message_id = t.id and c.json_key='c'
LEFT JOIN ds_params i ON i.message_id = t.id and i.json_key='i'
LEFT JOIN ds_params j ON j.message_id = t.id and j.json_key='j'
SET t.template = REPLACE(REPLACE(REPLACE(
REPLACE(REPLACE(t.template, CONCAT('{', IFNULL(a.json_key, '') , '}')
, IFNULL(a.json_value, '')),
CONCAT('{', IFNULL(b.json_key, '') , '}'), IFNULL(b.json_value, '')),
CONCAT('{', IFNULL(c.json_key, '') , '}'), IFNULL(c.json_value, '')),
CONCAT('{', IFNULL(i.json_key, '') , '}') ,IFNULL(i.json_value, '')),
CONCAT('{', IFNULL(j.json_key, '') , '}') ,IFNULL(j.json_value, ''));
You need to perform loop in this update. Since there is no fix key value pair so it is better to find the max key value pair to perform loop.
After that loop through each record using CURSOR to perform the update to replace your key with corresponding value. Since you already find out the max value of key pair so it will perform only till the max limit of loop for your query.
For reference you may find this link for details on CURSOR.
DECLARE a, b VARCHAR(10);
DECLARE cur1 CURSOR FOR SELECT DISTINCT json_key,json_value
FROM ds_params.t1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO a, b;
IF done THEN
LEAVE read_loop;
END IF;
UPDATE ds_message AS t
INNER JOIN ds_params m ON m.message_id = t.id
SET t.template = REPLACE(t.template, CONCAT('{', m.json_key , '}'), m.json_value)
WHERE M.JSON_KEY = b ;
END LOOP;
CLOSE cur1;
I am not sure about syntax but you may get the idea of implementing the same. If anything in syntax is not correct then kindly update the same.
I need to make trigger to increase the 2nd digit when the new value found to be a duplicate.
For Instance, I have a unique filed with 10 digits value. I want when someone insert same number it increase the second left digit like 0100012345. How I can do that? Thank you.
FirstName LastName Code
Houssam Salim 0100012345 to be 0200012345
Try this
I have found a solution with instead off trigger
'/*
CREATE TABLE [Employee1]
(
[id] VARCHAR(20) PRIMARY KEY,
[name] VARCHAR(50)
)
CREATE TRIGGER AutoIncrement_Trigger
ON [Employee1]
instead OF INSERT
AS
BEGIN
DECLARE #ch CHAR
DECLARE #num INT
IF EXISTS (SELECT 1
FROM Employee1 e
JOIN inserted i
ON i.id = e.id)
BEGIN
SET #num=(SELECT max(CONVERT(INT, substring(e.id, 1, 2))) + 1
FROM employee1 e
JOIN inserted i
ON substring(e.id, 3, len(e.id)) = substring(i.id, 3, len(i.id)))
INSERT INTO [Employee1]
(id,
name)
SELECT '0' + CONVERT(VARCHAR(10), #num)
+ substring(i.id, 3, len(i.id)),
e.name
FROM Employee1 e
JOIN inserted i
ON i.id = e.id
END
ELSE
BEGIN
INSERT INTO [Employee1]
(id,
name)
SELECT inserted.id,
inserted.name
FROM inserted
END
END
*/
INSERT INTO [Employee1]
VALUES ('0100012345',
'John')
SELECT *
FROM [Employee1]
INSERT INTO [Employee1]
VALUES ('0100012345',
'John')
SELECT *
FROM [Employee1]
'
I'm trying to make a query but I don't know how to do it. I'm a newbie in SQL querying, so please be patient.
Here is what I have:
select
count(*), sum(time), 'peter'
from
(select *
from ACTUATION
where OPERATOR != 'peter'
and team in (select eq1.name
from TEAMWORKS eq1
where operator1 = 'peter'
or operator2 = 'peter'
or operator3 = 'peter'
or operator4 = 'peter'
or operator5 = 'peter'
or operator6 = 'peter'
or operator7 = 'peter' )) as a
This works OK, but I need to do it for every operator in the table operators and don't know how to do it.
I've tried several subqueries and groups by, but I can not make it work properly.
Kind regards
EDIT:
Let's say I have this DataBase:
create table TEAMWORKS
(
operator1 varchar(50),
operator2 varchar(50),
operator3 varchar(50),
operator4 varchar(50),
operator5 varchar(50),
operator6 varchar(50),
operator7 varchar(50),
name varchar(50)
)
insert into TEAMWORKS (operator1,operator2,name) values ('Peter', 'Paul', 'Pe-Pa')
insert into TEAMWORKS (operator2,operator3,name) values ('Peter', 'John', 'Pe-Jo')
insert into TEAMWORKS (operator1,operator4,name) values ('John', 'Paul', 'Jo-Pa')
insert into TEAMWORKS (operator5,operator6,name) values ('John', 'Peter', 'Jo-Pe')
create table OPERATORS
(
name varchar(50),
surname varchar(50)
)
insert into OPERATORS (name,surname) values ('Peter', 'Font')
insert into OPERATORS (name,surname) values ('Paul', 'Bridges')
insert into OPERATORS (name,surname) values ('John', 'Oldfield')
create table ACTUATION
(
ID int,
time int,
operator varchar(50),
team varchar(50),
description varchar(999)
)
insert into ACTUATION (ID,time,operator,team,description) values (1,30,'Peter', '','Pick flowers')
insert into ACTUATION (ID,time,operator,team,description) values (2,15,'Paul', '','Throw flowers')
insert into ACTUATION (ID,time,operator,team,description) values (3,30,'Peter', 'Jo-Pe','Pick stones')
insert into ACTUATION (ID,time,operator,team,description) values (4,5,'John', 'Jo-Pe','Throw stones')
insert into ACTUATION (ID,time,operator,team,description) values (5,15,'Paul', 'Jo-Pa','Throw tables')
insert into ACTUATION (ID,time,operator,team,description) values (6,30,'Peter', 'Pe-Pa','Pick tables')
And I need to get the time used by Every operator in table OPERATORS where he is not the main operator in Table ACTUATIONS, but part of a TEAM in the ACTUATIONS.
In the given example, I would like to get as result:
Operator #Actuations (count) Time(sum) 'Origin (only for clarifying, list not needed)
Peter 1 5 'from actuation #4
Paul 1 30 'from actuation #6
John 2 45 'form actuations #3 and #5
Hope now it's more clear
EDIT 2:
You have a working example here: http://sqlfiddle.com/#!3/91373/6/0
That's the desired result, but obviously I would not be able to use unions as I would not know the Operators.
Edit:
After OP having altered the question, here is a working query for your example:
select top 1000
o.name
, count(1)
, sum(a.time)
from OPERATORS o
left join (
select
unpvt.Operator
, unpvt.ColName
, unpvt.name
from
(select name, operator1, operator2, operator3, operator4, operator5, operator6, operator7
from TEAMWORKS) ot
UNPIVOT (
Operator FOR ColName IN (operator1, operator2, operator3, operator4, operator5, operator6, operator7)
) as unpvt
) tw on o.name = tw.Operator
left join ACTUATION a on a.team = tw.name
where a.operator != o.name
group by o.name
This returns your decired result :)
Old Post:
I don't know the structure of the database, but I've had a go at guessing.
Firstly, i create to temporary tables in T-SQL - this is done for testing.
I've previously been down-voted for using temporary tables without descriptions in answers on SO for being to complicated, so please ask if you don't understand
declare #ACTUATION table(
time datetime default getdate()
, Operator varchar(8)
, Workteam varchar(8)
)
insert into #ACTUATION (Operator, Workteam)
select 'Gunnar', 'Peter'
union all select 'Peter', 'Gunnar'
We also need the table Teamworks:
declare #TEAMWORKS table(
time datetime default getdate()
, sometext varchar(32)
, operator1 varchar(8)
, operator2 varchar(8)
, operator3 varchar(8)
, operator4 varchar(8)
, operator5 varchar(8)
, operator6 varchar(8)
, operator7 varchar(8)
)
insert into #TEAMWORKS(sometext, operator1, operator2, operator3, operator4, operator5, operator6, operator7)
select 'Blah Blah', 'Gunnar', 'Jack', 'Sam', 'Joe', 'Lee', 'Jane', 'Jim'
union all select 'More Blah', 'Bob', 'Sal', 'Phil', 'Clark', 'Jones', 'Sue', 'Peter'
union all select 'Even more Blaah', 'Im', 'Running', 'out of', 'dummy', 'names', 'Peter', 'Gunnar'
What I've done here is to create two "virtual" tables, which only consist as variables. Eg. they are recreated each time the query is run. However, I think that they are a great tool when trying to visualize.
Next step is to UNPIVOT the operators to a more normalized structure.
This is done using the following query:
select
unpvt.time
, unpvt.sometext
, unpvt.Operator
, unpvt.ColName
from
(select time, sometext, operator1, operator2, operator3, operator4, operator5, operator6, operator7
from #TEAMWORKS) ot
UNPIVOT (
Operator FOR ColName IN (operator1, operator2, operator3, operator4, operator5, operator6, operator7)
) as unpvt;
This query should make a great starting point for further joins.
For instance, I assume that this is (partly) the result you want:
select
a.Operator
, count(1)
, max(t.time)
from #ACTUATION a
left join (
select
unpvt.Operator
, unpvt.time
from (
select time, sometext, operator1, operator2, operator3, operator4, operator5, operator6, operator7
from #TEAMWORKS
) ot
UNPIVOT (
Operator FOR ColName IN (operator1, operator2, operator3, operator4, operator5, operator6, operator7)
) as unpvt
) t on a.Workteam = t.Operator
where a.Operator != t.Operator
group by a.Operator
I need to list all the order done with every customer , So if a certain customer had passed 6 order then we need to list order1 | Order2| order3| ...
I have a table called Order where we have the Client Id , I am using SqlServer 2008 R2 , I have tried different approach but with no success , they run for ever and never gave a result :s , Here my lates try :
SELECT convert(varchar(1),isnull(user.Order.OrderId,'')) +' | '+ convert(varchar(1),isnull(Order_1.OrderId,'')) +' | '+convert(varchar(1),isnull(Order_2.OrderId,'')) +' | '+convert(varchar(1),isnull(Order_3.OrderId,'')) +' | '+convert(varchar(1),isnull(Order_4.OrderId,'')) +' | '+convert(varchar(1),isnull(Order_5.OrderId,'')) as OrderIdList,
user.client.kdnr
FROM user.Order
left outer JOIN user.Order AS Order_1 ON user.Order.clientnr = Order_1.clientnr AND Order_1.OrderId <> user.Order.OrderId and Order.orderDate < Order_1.orderDate
left outer JOIN user.Orderold AS Order_2 ON user.Order.clientnr = Order_2.clientnr AND Order_2.OrderId not in ( user.Order.OrderId , Order_1.OrderId ) and Order_1.orderDate < Order_2.orderDate
left outer JOIN user.Orderold AS Order_3 ON user.Order.clientnr = Order_3.clientnr AND Order_3.OrderId not in ( user.Order.OrderId , Order_1.OrderId, Order_2.OrderId ) and Order_1.orderDate < Order_2.orderDate
left outer JOIN user.Orderold AS Order_4 ON user.Order.clientnr = Order_4.clientnr AND Order_4.OrderId not in ( user.Order.OrderId , Order_1.OrderId, Order_2.OrderId, Order_3.OrderId ) and Order_2.orderDate < Order_3.orderDate
left outer JOIN user.Orderold AS Order_5 ON user.Order.clientnr = Order_5.clientnr AND Order_5.OrderId not in ( user.Order.OrderId , Order_1.OrderId, Order_2.OrderId, Order_3.OrderId, Order_4.OrderId ) and Order_3.orderDate < Order_4.orderDate
INNER JOIN user.client ON Order_1.clientnr = user.client.kdnr
group by client.kdnr ,user.client.name1, user.client.firstname, user.Order.OrderId, Order_1.OrderId,Order_1.Ordernr,Order_2.OrderId ,Order_3.OrderId,Order_4.OrderId,Order_5.OrderId `
Does any body have an dea how would I do that Correctly?
By using XML capabilities of SQL Server 2005 and above you can easily and efficiently generate comma separated values.
Try this (adjust according to your table and column names):
-- Sample tables
declare #Customer table
(
CustomerId int,
Name varchar(50)
)
declare #Order table
(
OrderId int,
CustomerId int
)
-- Sample data
insert into #Customer (CustomerId, Name) values (1, 'Alice')
insert into #Customer (CustomerId, Name) values (2, 'Mary')
insert into #Customer (CustomerId, Name) values (3, 'David')
insert into #Order (OrderId, CustomerId) values (1, 1)
insert into #Order (OrderId, CustomerId) values (2, 1)
insert into #Order (OrderId, CustomerId) values (3, 1)
insert into #Order (OrderId, CustomerId) values (4, 2)
insert into #Order (OrderId, CustomerId) values (5, 2)
insert into #Order (OrderId, CustomerId) values (6, 3)
----select * from #Customer
----select * from #Order
/* Actual Query that would add the OrderId from #Order table as a comma separated list against relevant Customer */
SELECT Customer.CustomerId as CustomerId, Customer.Name,
(
SELECT Convert(varchar(1), O.OrderId) + ','
FROM #Order AS O
WHERE O.CustomerId = Customer.CustomerId
ORDER BY O.OrderId
FOR XML PATH('')
) AS OrderList
FROM #Customer AS Customer
Well, i can't give you a complete answer, but i can tell you how to solve it. Try to use Common Table Expressions (http://msdn.microsoft.com/en-us/library/ms177410(v=sql.105).aspx).
With this you can join to your own resultset, where you make a recursive loop to solve this issue.
Hope it helps you
I have large table, with around 200 fields. Around a 100 of those fields are to be mapped to one field when creating a dimension table from it. The problem is I have to add the values of those 100 fields one-by-one through like a 100 insert statements. Is there like a loop or something with which i can achieve this more efficiently?
Here's an example of the code:
insert into DimTableA(visit_no, patient, facility, icd9, icd9_flag, ip_op)
select D.registration, D3.med_number, D3.Hosp_Id, D.final_diagnosis_18,'d',IF(D3.Admit_Type in(1,2,3),'Inpatient','Outpatient'),
from svch_dischs3_s D3, svch_diags_s D
insert into DimTableA(visit_no, patient, facility, icd9, icd9_flag, ip_op)
select D.registration, D3.med_number, D3.Hosp_Id, D.final_diagnosis_19,'d',IF(D3.Admit_Type in(1,2,3),'Inpatient','Outpatient'),
from svch_dischs3_s D3, svch_diags_s D
insert into DimTableA(visit_no, patient, facility, icd9, icd9_flag, ip_op)
select D.registration, D3.med_number, D3.Hosp_Id, D.final_diagnosis_20,'d',IF(D3.Admit_Type in(1,2,3),'Inpatient','Outpatient'),
from svch_dischs3_s D3, svch_diags_s D;
......... and so on
The only field name that changes is the 'icd9' input( i.e D.final_diagnosis_18, final_diagnosis_19, final_diagnosis_20 ....)
Any help would be really appreciated, lads. :)
You could unpivot those columns using a cross join to a fixed set of numbers like this:
insert into DimTableA (
visit_no,
patient,
facility,
icd9,
icd9_flag,
ip_op
)
select
D.registration,
D3.med_number,
D3.Hosp_Id,
case N.number
when 1 then D.final_diagnosis_18
when 2 then D.final_diagnosis_19
when 3 then D.final_diagnosis_20
...
end,
'd',
IF(D3.Admit_Type in(1,2,3),'Inpatient','Outpatient')
from
svch_dischs3_s D3,
svch_diags_s D,
(
select 1 as number union all
select 2 union all
select 3 union all
... /* up to the number of columns to unpivot */
) N
You could create and populate a persistent numbers table instead of the inline view and use the necessary subset of that table in your query. In that case the query would change like this
...
from
svch_dischs3_s D3,
svch_diags_s D,
numbers N
where N.number between 1 and … /* the number of columns to unpivot */
You could try running a single INSERT with a UNION in the sub select.
Your current SQL has a Cartesian join in it so I am going to take a guess that you are missing a join somewhere. Anyway, this should give you an idea of what I am driving at:
insert into DimTableA(visit_no, patient, facility, icd9, icd9_flag, ip_op)
select D.registration, D3.med_number, D3.Hosp_Id, D.final_diagnosis_18,'d',IF(D3.Admit_Type in(1,2,3),'Inpatient','Outpatient')
from svch_dischs3_s D3, svch_diags_s D
-- where D3.???? = D.????
union
select D.registration, D3.med_number, D3.Hosp_Id, D.final_diagnosis_19,'d',IF(D3.Admit_Type in(1,2,3),'Inpatient','Outpatient')
from svch_dischs3_s D3, svch_diags_s D
-- where D3.???? = D.????
union
select D.registration, D3.med_number, D3.Hosp_Id, D.final_diagnosis_20,'d',IF(D3.Admit_Type in(1,2,3),'Inpatient','Outpatient')
from svch_dischs3_s D3, svch_diags_s D
-- where D3.???? = D.????;
Here is a more theoretical example:
create table dimTable
(id int unsigned not null default 0,
field varchar(50)
);
create table sourceTable
(id int unsigned not null default 0,
field1 varchar(50),
field2 varchar(50),
field3 varchar(50),
field4 varchar(50),
field5 varchar(50)
);
insert into sourceTable (id,field1,field2,field3,field4,field5) values (1,"hello","these","are","some","values");
insert into sourceTable (id,field1,field2,field3,field4,field5) values (2,"hello2","these2","are2","some2","values2");
insert into sourceTable (id,field1,field2,field3,field4,field5) values (3,"hello3","these3","are3","some3","values3");
insert into sourceTable (id,field1,field2,field3,field4,field5) values (4,"hello4","these4","are4","some4","values4");
insert into sourceTable (id,field1,field2,field3,field4,field5) values (5,"hello5","these5","are5","some5","values5");
insert into dimTable (id, field)
select id,field1 from sourceTable
union
select id,field2 from sourceTable
union
select id,field3 from sourceTable
union
select id,field4 from sourceTable
union
select id,field5 from sourceTable;
select *
from dimTable;
Hope it helps!
A stored procedure would solve your problem. You may only require to pass field values to be inserted and the suffix to the D.final_diagnosis_ field.
An example code snippet is shown below:
drop procedure if exists proc_insert_icd9;
delimiter //
create procedure proc_insert_icd9( final_diagnosis_suffix int )
begin
declare suffixId int;
declare sql_insert_str varchar( 255 );
declare sql_select_str varchar( 255 );
declare sql_temp varchar( 255 );
set suffixId = final_diagnosis_suffix;
set sql_insert_str = 'insert into DimTableA(visit_no, patient, facility, icd9, icd9_flag, ip_op) ';
set sql_select_str = concat( 'select D.registration, D3.med_number, D3.Hosp_Id, D.final_diagnosis_', suffixId, ', ''d'', IF(D3.Admit_Type in(1,2,3), ''Inpatient'', ''Outpatient'' ) from svch_dischs3_s D3, svch_diags_s D' );
select concat( sql_insert_str, sql_select_str ) into #sql_temp;
prepare stmt from #sql_temp;
execute stmt;
end;
//
delimiter ;
Now try calling the procedure that many number of times you require with correct suffix value for final_diagnosis field as parameter.
Example:
call proc_insert_icd9( 18 );
call proc_insert_icd9( 19 );
Note: You can modify procedure to include
more input parameters to handle a where clause, etc..
a where clause to the select statement.