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
Related
I know this question was already asked in a similar way, but I could not found any with an alias in the where clause.
I have a table structure like this:
CREATE TABLE Orders
( ID int NOT NULL Primary Key
, OrderNr VARCHAR(6) NOT NULL
, Date DATE NOT NULL
, Time CHAR(6) NOT NULL
, GeoCode CHAR(6) NULL) ;
My insert looks like this:
INSERT INTO orders (ID, OrderNr, Date, Time, GeoCode) VALUES (1, '123456', '2022-02-
15', '111110', '4022')
, (2, '123457', '2022-02-15', '121210', '4022')
, (3, '123455', '2021-04-15', '171515', '4020')
, (4, '123455', '2021-04-16', '150302', '4022')
, (5, '123466', '2022-03-03', '191810', '4020')
, (6, '123466', '2022-03-04', '121410', '4022')
Now I´m trying to get the latest Date and Time values for all OrderNr like this:
SELECT ID, OrderNr, MAX(cast(concat(Date, ' ', cast(Time as Time)) as datetime)) as
DateAndTime, GeoCode
FROM Orders o1
GROUP BY OrderNr
The Results shows the right latest date and time but the GeoCode is wrong. E.g for the
OrderNr 123455 it is 4020 but should be 4022.
I know that similar question were already asked but I cant use the alias in the where clause. Can somebody explain to me what I´m doing wrong?
Thank you very much in advance.
If your mysql version support ROW_NUMBER window function you can try this
SELECT *
FROM (
SELECT ID,
OrderNr,
cast(concat(Date, ' ', cast(Time as Time)) as datetime) DateAndTime,
GeoCode,
ROW_NUMBER() OVER(PARTITION BY OrderNr ORDER BY cast(concat(Date, ' ', cast(Time as Time)) as datetime) DESC) rn
FROM Orders o1
) t1
WHERE rn = 1
or use subquery with EXISTS
SELECT *
FROM Orders o1
WHERE EXISTS (
SELECT 1
FROM Orders oo
WHERE oo.OrderNr = o1.OrderNr
HAVING MAX(oo.Date) = o1.Date
)
sqlfiddle
I have this script and it works in SQL Server 2012, but I need to use it in SQL Server 2008. Does anyone have a suggestion ?
Create table #TempOne (ID int)
Insert into #TempOne
Values (1), (2), (34), (121), (72), (34), (81), (26), (234)
Create table #TempTwo
(
ID int,
Name Varchar(30),
Age int
)
Insert into #TempTwo
Values (18, 'P', 291), (11, 'P', 21), (13, 'P', 11), (21, 'P', 21)
Select
LEAD(ID,3) Over(Order By ID) As ID, Name , Age
From
(Select ID, NULL As Name, NULL As Age
From #TempOne
Union
Select NULL, Name, age
From #TempTwo) a
Your query would look something like the following:
WITH a AS (
Select ID , NULL As Name,NULL As Age
From #TempOne
Union
Select NULL, Name,age From #TempTwo
),
an AS (
SELECT
*,
rn=ROW_NUMBER() OVER (ORDER BY ID)
FROM
a
)
SELECT
an_r.ID,an_l.Name,an_l.Age
FROM
an AS an_l
LEFT JOIN an AS an_r ON
an_r.rn=an_l.rn+3;
What this does, is first number the rows using ROW_NUMBER, ordered by ID. In that case, LEAD(ID,3) can be done by self-joining the numbered set on right-rn=left-rn+3.
I want to get the average number (Attendee NPS) from a SQL table I've already put together.
I've encased the initial table in a new select statement so I can take the average of distinct values. Is there something in my Join clause that is preventing this from working?
Im getting the following error:
ERROR: missing FROM-clause entry for table "gizmo" Position: 12
SELECT
avg(bigtable.gizmo.attendee_nps)
FROM
(
SELECT DISTINCT
attendee_survey_results.swoop_event_id AS "Swoop ID",
attendee_survey_results.startup_weekend_city AS "SW City",
swooptable.start_date AS "Date",
gizmo.attendee_nps AS "Attendee NPS"
FROM attendee_survey_results
JOIN
(
SELECT
swoop_event_id,
(
100 * count(CASE WHEN attendee_nps >= 9 THEN 1 END)
/ count(attendee_nps)
- 100 * count(CASE WHEN attendee_nps <= 6 THEN 1 END)
/ count(attendee_nps)
) AS "attendee_nps"
FROM attendee_survey_results
GROUP BY swoop_event_id
) AS "gizmo"
ON gizmo.swoop_event_id = attendee_survey_results.swoop_event_id
JOIN
(
SELECT eid,start_date,manager_email
FROM events
) AS "swooptable"
ON gizmo.swoop_event_id = swooptable.eid
) AS bigtable
[edit, ok you don't have a single problem, but the request at the bottom should work]
3 part notation bigtable.gizmo.attendee_nps
You can't use this bigtable.gizmo.attendee_nps, this is the "with DB" specific syntax : db_name.tbl_name.col_name.
You should use a table_or_alias.col_name_or_alias notation
In sub query you loose the deep table name of every deep-1 :
-- with the deep explicite
SELECT `d0`.`new_field`
FROM (
-- implicite `d1` table
SELECT `new_field`
FROM (
-- with the deep `d2` explicite and alias of field
SELECT `d2`.`field` AS `new_field`
FROM (
-- without the explicite `d3` table and `field` field
SELECT *
FROM (
-- output a `field` => 12
SELECT 12 as `field`
) AS `d3`
) AS `d2`
) AS `d1`
) AS `d0`
-- print `new_field` => 12
Access deep-1 aliased field
SELECT `attendee_nps`
FROM
(
SELECT `attendee_nps` AS `new_alias_field`
FROM attendee_survey_results
) AS bigtable
Unknown column 'attendee_nps' in 'field list'
When you make a field alias in deep-1 query, deep-0 can only access the alias new_alias_field, the original field no longer exist.
Double quote " table alias
FROM (
-- ...
) AS "bigtable"
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '"bigtable"' at line N
MySql don't allow the use of " to make table alias (it's technically ok for field alias).
You should use the mysql back quote to escape table alias name, like AS `My Table Alias`
Correct query :
SQL Fiddle
MySQL 5.6 Schema Setup:
CREATE TABLE events
(`eid` int, `start_date` varchar(10), `manager_email` varchar(15))
;
INSERT INTO events
(`eid`, `start_date`, `manager_email`)
VALUES
(1, '2016-11-11', 'mail_1#mail.com'),
(2, '2016-11-12', 'mail_2#mail.com'),
(3, '2016-11-13', 'mail_3#mail.com'),
(4, '2016-11-14', 'mail_4#mail.com'),
(5, '2016-11-15', 'mail_5#mail.com'),
(6, '2016-11-16', 'mail_6#mail.com'),
(7, '2016-11-17', 'mail_7#mail.com')
;
CREATE TABLE attendee_survey_results
(`id` int, `swoop_event_id` int, `startup_weekend_city` varchar(6), `attendee_nps` int)
;
INSERT INTO attendee_survey_results
(`id`, `swoop_event_id`, `startup_weekend_city`, `attendee_nps`)
VALUES
(1, 1, 'city_1', 1),
(2, 2, 'city_2', 22),
(3, 3, 'city_3', 3),
(4, 1, 'city_4', 4),
(5, 2, 'city_5', 5),
(6, 3, 'city_6', 9),
(7, 7, 'city_7', 17)
;
Query 1:
SELECT
AVG(`bigtable`.`attendee_nps`)
FROM
(
SELECT DISTINCT
`asr`.`swoop_event_id` AS `Swoop ID`,
`asr`.`startup_weekend_city` AS `SW City`,
`swooptable`.`start_date` AS `date`,
`gizmo`.`attendee_nps` AS `attendee_nps`
FROM `attendee_survey_results` AS `asr`
JOIN
(
SELECT
`swoop_event_id`,
(
100 * count(CASE WHEN `attendee_nps` >= 9 THEN 1 END)
/ count(`attendee_nps`)
- 100 * count(CASE WHEN `attendee_nps` <= 6 THEN 1 END)
/ count(`attendee_nps`)
) AS `attendee_nps`
FROM `attendee_survey_results`
GROUP BY `swoop_event_id`
) AS `gizmo`
ON `gizmo`.`swoop_event_id` = `asr`.`swoop_event_id`
JOIN
(
SELECT `eid`, `start_date`, `manager_email`
FROM `events`
) AS `swooptable`
ON `gizmo`.`swoop_event_id` = `swooptable`.`eid`
) AS `bigtable`
Results:
| AVG(`bigtable`.`attendee_nps`) |
|--------------------------------|
| -14.28571429 |
I am trying to construct a query that will allow me to "filter" on pairs of columns for particular criteria. I need to be able to construct multiple filters for the same given pair. The end result should only return instances that have data for the case where all filters are applied.
I constructed a trivial example demonstrating what I would like to be able to do.
Using the follow table definition:
DROP TABLE IF EXISTS foo;
CREATE TEMPORARY TABLE `foo` (
`ID` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`Index` INT UNSIGNED NOT NULL,
`Header` VARCHAR(50) NOT NULL,
`Value` VARCHAR(255) NOT NULL,
PRIMARY KEY (`ID`),
UNIQUE INDEX `ID_UNIQUE` (`ID` ASC));
INSERT INTO `foo` (`Index`, `Header`, `Value`)
VALUES
(0, 'Header_1', 'a'),
(0, 'Header_2', 'b'),
(1, 'Header_1', 'a'),
(1, 'Header_2', 'c');
I would like a query that would return the following, given that you are looking for the case where 'Header_1' == 'a' and 'header_2' == 'b':
Index | Header | Value
------------------------
0 | Header_1 | a
0 | Header_2 | b
My current attempt is as follows:
SELECT `Index`, `Header`, `Value` FROM `foo`
WHERE (
(`Header` = 'Header_1') AND (`Value` = 'a')
OR (
(`Header` = 'Header_2') AND (`Value` = 'b')
)
)
GROUP BY `Header`, `Value`
HAVING COUNT(DISTINCT `Index`) = 2
ORDER BY `Index`, `Header`;
That code returns the following:
Index | Header | Value
------------------------
0 | Header_1 | a
I am missing one of my return rows. How can I restructure the query to return all of the matching rows?
Note that I declared the table as a temporary table. This is important, as I am working with temporary tables, and they have special restrictions to keep in mind (namely not being able to open it more than once in the same statement).
Your query returns only header_1 because the clause:
HAVING COUNT(DISTINCT `Index`) = 2
is only correct for Header_1.
Header_2 has count=1, therefore removed from the end result.
To get a clearer picture of what i say use:
SELECT `Index`, `Header`, `Value`, COUNT(DISTINCT `Index`) FROM `foo`
WHERE (
(`Header` = 'Header_1') AND (`Value` = 'a')
OR (
(`Header` = 'Header_2') AND (`Value` = 'b')
)
)
GROUP BY `Header`, `Value`
ORDER BY `Index`, `Header`;
and take a look at the last column.
I couldn't figure out how to do this with only the one temporary table. I'm not happy with this result, but at least it works.
DROP TABLE IF EXISTS `foo2`;
CREATE TEMPORARY TABLE `foo2` (
SELECT `Index` FROM `foo`
WHERE (
(`Header` = 'Header_1') AND (`Value` = 'a')
OR (
(`Header` = 'Header_2') AND (`Value` = 'b')
)
)
GROUP BY `Index`
HAVING COUNT(DISTINCT `Header`) = 2
);
SELECT DISTINCT t1.`Index`, t1.`Header`, t1.`Value` FROM `foo` t1
INNER JOIN `foo2` t2 ON t2.`Index` = t1.`Index`
ORDER BY t1.`Index`, t1.`Header`;
How about...
SELECT `index`
FROM foo
WHERE (header,value) IN (('header_1','a'))
OR (header,value) IN (('header_2','b'))
GROUP
BY `index`
HAVING COUNT(*) = 2;
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.