Group by with text and date time combination - sql-server-2008

I have a table
id col1 col2 namecol1 datetime1 teamcol1 namecol2 datetime2
1 12345 2345 name1 2014-10-13 11:57:24.713 teama
2 12345 2345 name1 2014-10-13 11:57:24.713 teamb abc 2014-11-29 09:55:38.533
3 12345 2345 name1 2014-10-13 11:57:24.713 teamb bcd 2014-12-02 06:35:38.917
4 12345 2345 name1 2014-10-13 11:57:24.713 teamc def 2014-12-22 11:57:54.863
5 12345 2345 name1 2014-10-13 11:57:24.713 teamd efg 2015-01-03 13:28:24.717
I need this output:
col1 col2 Team1 DateTime1 Team2 DateTime2 Team3 DateTime3
12345 2345 bcd 2014-12-02 06:35:38.917 def 2014-12-22 11:57:54.863 efg 2015-01-03 13:28:24.717
I tried this query:
SELECT
MAX(CASE WHEN teamcol1='teamb' THEN namecol2 END) AS Team1,
CONVERT(DATE, MAX(CASE WHEN teamcol1='teamb' THEN datetime2 END), 105) AS DateTime1,
MAX(CASE WHEN teamcol1='teamc' THEN namecol2 END) AS PRECON_AUDIT,
CONVERT(DATE,MAX(CASE WHEN teamcol1='teamc' THEN datetime2 END), 105) AS DateTime2,
MAX(CASE WHEN teamcol1 IN ('teamd') THEN namecol2 END) AS Team3,
CONVERT(DATE,MAX(CASE WHEN teamcol1 IN ('teamd') THEN datetime2 END),105) AS DateTime3,
col1, col2
FROM
(SELECT *
FROM table1) Z
WHERE
col1 = '12345'
GROUP BY
col1, col2
Output of this query:
col1 col2 Team1 DateTime1 Team2 DateTime2 Team3 DateTime3
12345 2345 abc 2014-12-02 06:35:38.917 def 2014-12-22 11:57:54.863 efg 2015-01-03 13:28:24.717
I am using SQL Server 2008.
Thanks in advance.
[EDIT]
Table1 is like audit table which will have multiple entries with different combination of col1,col2.
I need to display for each combination of col1,col2 different team names and with appropriate namecol2 and datetime2 columns.
When i use the query mentioned above it is giving me the output correctly if there is no repetition in teamcol1. If there is a repetition in teamcol1 (as mentioned in question) it is giving me the wrong namecol2.
In case of repetition in teamcol1 i need latest namecol2 and datetime2 ( from the table i need namecol2 -- bcd and datetime2 -- 2014-12-02 06:35:38.917)

At first make a list of all groups (DISTINCT col1, col2).
Then for each group find one row with the latest datetime2. Do it three times, for each teamb, teamc, teamd.
You can put complex query inside OUTER APPLY with whatever logic and ordering you need.
DECLARE #T TABLE (id int, col1 int, col2 int, namecol1 varchar(255), [datetime1] datetime, teamcol1 varchar(255), namecol2 varchar(255), [datetime2] datetime);
INSERT INTO #T (id, col1, col2, namecol1, datetime1, teamcol1, namecol2, datetime2) VALUES (1, 12345, 2345, 'name1', '2014-10-13 11:57:24.713', 'teama', NULL, NULL);
INSERT INTO #T (id, col1, col2, namecol1, datetime1, teamcol1, namecol2, datetime2) VALUES (2, 12345, 2345, 'name1', '2014-10-13 11:57:24.713', 'teamb', 'abc', '2014-11-29 09:55:38.533');
INSERT INTO #T (id, col1, col2, namecol1, datetime1, teamcol1, namecol2, datetime2) VALUES (3, 12345, 2345, 'name1', '2014-10-13 11:57:24.713', 'teamb', 'bcd', '2014-12-02 06:35:38.917');
INSERT INTO #T (id, col1, col2, namecol1, datetime1, teamcol1, namecol2, datetime2) VALUES (4, 12345, 2345, 'name1', '2014-10-13 11:57:24.713', 'teamc', 'def', '2014-12-22 11:57:54.863');
INSERT INTO #T (id, col1, col2, namecol1, datetime1, teamcol1, namecol2, datetime2) VALUES (5, 12345, 2345, 'name1', '2014-10-13 11:57:24.713', 'teamd', 'efg', '2015-01-03 13:28:24.717');
WITH
CTE_Groups
AS
(
SELECT DISTINCT col1, col2
FROM #T
)
SELECT *
FROM
CTE_Groups
OUTER APPLY
(
SELECT TOP(1)
TT.namecol2 AS Team1
, TT.[datetime2] AS DateTime1
FROM #T AS TT
WHERE
TT.teamcol1 = 'teamb'
AND TT.col1 = CTE_Groups.col1
AND TT.col2 = CTE_Groups.col2
ORDER BY TT.[datetime2] DESC
) OA_teamb
OUTER APPLY
(
SELECT TOP(1)
TT.namecol2 AS Team2
, TT.[datetime2] AS DateTime2
FROM #T AS TT
WHERE
TT.teamcol1 = 'teamc'
AND TT.col1 = CTE_Groups.col1
AND TT.col2 = CTE_Groups.col2
ORDER BY TT.[datetime2] DESC
) OA_teamc
OUTER APPLY
(
SELECT TOP(1)
TT.namecol2 AS Team3
, TT.[datetime2] AS DateTime3
FROM #T AS TT
WHERE
TT.teamcol1 = 'teamd'
AND TT.col1 = CTE_Groups.col1
AND TT.col2 = CTE_Groups.col2
ORDER BY TT.[datetime2] DESC
) OA_teamd
Result set:
col1 col2 Team1 DateTime1 Team2 DateTime2 Team3 DateTime3
12345 2345 bcd 2014-12-02 06:35:38.917 def 2014-12-22 11:57:54.863 efg 2015-01-03 13:28:24.717
If there is no teamb for a certain combination of col1 and col2, there will be NULLs in Team1 and DateTime1. Same for teamc and teamd.

Related

Mysql query to decide the type if group by value is greater than 1 consider as type 2 else 1

I want to write a case condition in mysql query when grouped by channelvalue if the count is more than 1 it is considered as type_id 3 if there is no duplicates for the channelvalue then the type_id should be 2
else 0
select b.ChannelValue
case
when count(*),ChannelValue from tableb group by ChannelValue having count(*)=1 then 2
when count(*),ChannelValue from tableb group by ChannelValue having count(*)>1 then 3
else 0 END AS type_id
from tablea a inner join tableb b
on a.ChannelValue = b.ChannelValue;
Help me out !
You could use something like below:
select ChannelValue,
case
when (
select count(*) from tableb
group by tableb.ChannelValue
having tableb.ChannelValue = tablea.ChannelValue) = 1 then 2
when(
select count(*) from tableb
group by tableb.ChannelValue
having tableb.ChannelValue = tablea.ChannelValue) > 1 then 3
else 0
END as type_id
from tablea;
Say if you have this test data:
INSERT INTO tablea (PersonID, ChannelValue)
VALUES (1, 100),
(2, 200),
(3, 300);
INSERT INTO tableb (testID, ChannelValue, characterid)
VALUES (1, 100, 1),
(2, 100,2),
(3, 300, 3);
The query would return:
ChannelValue
type_id
100
3
200
0
300
2

How will I fix this table using MySQL?

I am new to MySQL. I am using MySQL 8.0.
My schema and sample data is as follows:
CREATE TABLE AA (
A int
);
insert into AA (A) values (1);
insert into AA (A) values (1);
insert into AA (A) values (2);
insert into AA (A) values (2);
insert into AA (A) values (1);
insert into AA (A) values (3);
CREATE TABLE BB (
code int,
description varchar(30)
);
insert into BB (code, description) values (1, 'Male');
insert into BB (code, description) values (2, 'Female');
Here's my code
with totalcount as (
select code as 'CODE',
description as 'SEX',
count(A) AS 'TOTAL',
ROUND((COUNT(A) * 100.0) / (SELECT COUNT(A) FROM AA),2) AS 'PERCENT',
sum(count(A)) over (order by CODE asc) AS 'CUMULATIVE',
ROUND((SUM(COUNT(A)) OVER (ORDER BY CODE ) / (SELECT COUNT(A) FROM AA) *100 ),2) AS 'CUMPERCENT'
from AA, BB
where AA.A= BB.code
group by AA.A
)
select *
from totalcount
UNION ALL
SELECT '0' CODE, 'TOTAL' SEX, SUM(TOTAL), SUM(PERCENT), '0' CUMULATIVE, '0.00' CUMPERCENT
from totalcount
ORDER BY CODE;
The output was this
CODE | SEX | TOTAL | PERCENT | CUMULATIVE | CUMPERCENT
0 TOTAL 5 100.00 0 0.00
1 MALE 3 60.00 3 60.00
2 FEMALE 2 40.00 5 100.00
I used UNION since I want the total of these items. In this case, I inserted 0 in TOTAL of SEX column to put it in the first row. Is there another way aside from using UNION and inserting code 0?
As you can see from my table BB, there are only code 1 and 2 for male and female, respectively. I want to show that the value not in this table should be in NOT VALID.
CODE | SEX | TOTAL | PERCENT | CUMULATIVE | CUMPERCENT
0 TOTAL 6 100.00 0 0.00
1 MALE 3 50.00 3 50.00
2 FEMALE 2 33.33 5 83.33
3 NOT VALID 1 16.67 6 100.00
Can you help me with this? Thank you.
This is a very tricky reporting question. One approach uses GROUP BY ROLLUP to generate the total row, along with judicious use of COALESCE to fill in the missing values per your requirements.
SELECT
COALESCE(t1.A, 0) AS CODE,
CASE WHEN t1.A IS NOT NULL THEN COALESCE(t2.DESCRIPTION, 'NOT VALID') ELSE 'TOTAL' END AS SEX,
t1.TOTAL,
ROUND(100.0 * t1.TOTAL / SUM(CASE WHEN t1.A IS NOT NULL THEN t1.TOTAL ELSE 0 END) OVER (), 2) AS PERCENT,
SUM(CASE WHEN t1.A IS NOT NULL THEN t1.TOTAL ELSE 0 END) OVER (ORDER BY t1.A) AS CUMULATIVE,
ROUND(100.0 * SUM(CASE WHEN t1.A IS NOT NULL THEN t1.TOTAL ELSE 0 END) OVER (ORDER BY t1.A) /
SUM(CASE WHEN t1.A IS NOT NULL THEN t1.TOTAL ELSE 0 END) OVER (), 2) AS CUMPERCENT
FROM
(
SELECT
A,
COUNT(*) AS TOTAL
FROM AA
GROUP BY A WITH ROLLUP
) t1
LEFT JOIN BB t2
ON t2.CODE = t1.A
ORDER BY
CODE;
Demo

SQL updating table

col1 | col2 | col3
-----------------------------
1 | 1 | somestring 12
1 | 2 | somestring sd
2 | 1 | somestring gvr
2 | 2 | somestring 46
3 | 1 | somestring sdf
3 | 2 | somestring 4
....
i want to UPDATE col3 WHERE col2 = 2
to be a CONCAT of col1 with col3
and REPLACE all ' ' with '-'.
Also if col1 < 10 add a leading '0' so '1' would be '01'
in total the value of col3 should be '01-somestring-sd'
can someone please help me with the statement?
Create data/insert data
CREATE TABLE Table1
(`col1` INT, `col2` INT, `col3` VARCHAR(255))
;
INSERT INTO Table1
(`col1`, `col2`, `col3`)
VALUES
(1, 1, 'somestring 12'),
(1, 2, 'somestring sd'),
(2, 1, 'somestring gvr'),
(2, 2, 'somestring 46'),
(3, 1, 'somestring sdf'),
(3, 2, 'somestring 4')
;
Query
UPDATE
Table1
SET
col3 =
CASE
WHEN col1 < 10
THEN REPLACE(CONCAT('0', col1, '-', col3), ' ', '-')
ELSE REPLACE(CONCAT(col1, '-', col3), ' ', '-')
END
WHERE
col2 = 2
Result
1 queries executed, 1 success, 0 errors, 0 warnings
Query: UPDATE Table1 SET col3 = CASE WHEN col1 < 10 THEN REPLACE(CONCAT('0', col1, '-', col3), ' ', '-') ELSE REPLACE(CONCAT(col1, '-',...
3 row(s) affected
Query
SELECT * FROM Table1
Result
col1 col2 col3
------ ------ ------------------
1 1 somestring 12
1 2 01-somestring-sd
2 1 somestring gvr
2 2 02-somestring-46
3 1 somestring sdf
3 2 03-somestring-4
UPDATE TABLE1 SET COL3=CONCAT(IF(COL1 < 10,0,''),COL1,REPLACE(COL3, ' ', '-' )) WHERE COL2=2
Try above code.
Hope this will helps.
Try this
Update table1
set
col3 = concat((case when col1>10 then '0'+col1 else col1 end),'-',REPLACE(COL3, ' ','-' ))
where col2=2
just use Concat and Replace
update table_name as t set t.col3 =
CONCAT(if(t.col1<10,0,''),t.col1,REPLACE(t.col‌​3,' ','-')) where
t.col2 =2;

Get Max in a Group based on a condition

ProjID Dno RNo Status DateApproved
100 1 1 Initiated 2014-12-31 09:15:58.000
100 1 1 Approved 2015-01-31 09:15:58.000
100 1 1 Approved 2015-02-01 09:15:58.000
100 1 1 Approved 2015-05-28 09:15:58.000
100 1 1 Approved 2015-06-20 09:15:58.000
101 1 1 Approved 2014-12-31 09:15:58.000
101 1 1 Approved 2015-01-31 09:15:58.000
101 1 1 Approved 2015-02-01 09:15:58.000
101 1 1 Approved 2015-05-28 09:15:58.000
101 1 1 Approved 2015-08-20 09:15:58.000
In the above example i have to get max(Dateapproved) as Dateapproved for each projectid.
if all the revision Status are approved in a particular group for eg :project id=101 has all rows in its group having a status as Approved so i have to get the max date : '2015-08-20 09:15:58.000'.But for Projectid=100 one status is still in Initiated State so we have to show Null as Dateapproved .
Thanks in Advance
My output should be like:
ProjId Dno Rno DateApproved
100 1 1 NUll
101 1 1 2015-08-20 09:15:58.000
Example code:
Create table #temp(
ProjectID varchar(35),
Documentno int,
Revisionno int,
Status varchar(35),
DateApproved Datetime)
insert into #temp values ( '100', 1, 1, 'Initiated','2014-12-31 09:15:58')
insert into #temp values ( '100', 1, 1, 'Approved','2015-01-31 09:15:58 ')
insert into #temp values ( '100', 1, 1, 'Approved','2015-02-01 09:15:58 ')
insert into #temp values ( '100', 1, 1, 'Approved','2015-05-28 09:15:58 ')
insert into #temp values ( '100', 1, 1, 'Approved','2015-06-20 09:15:58 ')
insert into #temp values ( '101', 1, 1, 'Approved','2014-12-31 09:15:58 ')
insert into #temp values ( '101', 1, 1, 'Approved','2015-01-31 09:15:58 ')
insert into #temp values ( '101', 1, 1, 'Approved','2015-02-01 09:15:58 ')
insert into #temp values ( '101', 1, 1, 'Approved','2015-05-28 09:15:58 ')
insert into #temp values ( '101', 1, 1, 'Approved','2015-08-20 09:15:58 ')
select * from #temp
Try this:
SELECT T.ProjectID,
Documentno as Dno,
Revisionno as RNo,
CASE WHEN SUM(CASE WHEN T.Status <> 'Approved' THEN 1 ELSE 0 END) = 0
THEN Max(T.DateApproved) ELSE NULL
END as DateApproved
from #temp T
GROUP BY T.ProjectId, Documentno , Revisionno
This gives the following output when run against your test data:
PROJECT ID DNo TNo DateApproved
100 1 1 NULL
101 1 1 2015-08-20 09:15:58.000
You can do this with a case statement and a conditional aggregate. Get the count of statuses that are not Approved using COUNT(NULLIF(Status, 'Approved')). If this is 0 then get the max date approved:
SELECT ProjectID,
DateApproved = CASE WHEN COUNT(NULLIF(Status, 'Approved')) = 0 THEN MAX(DateApproved) END
FROM #Temp
GROUP BY ProjectID;

Table column to row mysql query

I have 2 tables i need the result table almost converted from column to row converted
Table 1 : master_table
master_id user_name
1 name1
2 name2
3 name3
4 name4
Table 2 : master_meta_table
id master_id meta_key meta_value
1 1 f_name fname1
2 2 f_name fname2
3 2 l_name lname2
4 2 age age2
5 3 l_name lnam3
6 3 age age3
7 4 sex male
I would like to get the result like this
master_id user_name f_name l_name age sex
1 name1 fname1
2 name2 fname2 lname2 age2
3 name3 lname3 age3
4 name4 fname4 male
Please some one help me with this...
Try:
select
mt1.master_id,
mt1.user_name,
max(case when mt2.meta_key = 'f_name' then mt2.meta_value end) as fname,
max(case when mt2.meta_key = 'l_name' then mt2.meta_value end) as lname,
max(case when mt2.meta_key = 'age' then mt2.meta_value end) as age,
max(case when mt2.meta_key = 'sex' then mt2.meta_value end) as sex
from
master_table mt1
join master_meta_table mt2 on mt1.master_id = mt2.master_id
group by
mt1.master_id,
mt1.user_name
Fiddle: http://sqlfiddle.com/#!2/af277e/3/0
Here is your DDL
create table master_table
(
master_id int,
user_name varchar(20)
);
create table master_meta_table
(
id int,
master_id int,
meta_key varchar(20),
meta_value varchar(20)
);
insert into master_table
values (
1,'name1');
insert into master_table
values (
2,'name2');
insert into master_table
values (
3,'name3');
insert into master_table
values (
4,'name4');
insert into master_meta_table
values (
1,1,'f_name','fname1');
insert into master_meta_table
values (
2,2,'f_name','fname2');
insert into master_meta_table
values (
3,2,'l_name','lname2');
insert into master_meta_table
values (
4,2,'age','age2');
insert into master_meta_table
values (
5,3,'l_name','lname3');
insert into master_meta_table
values (
6,3,'age','age3');
insert into master_meta_table
values (
7,4,'sex','male');
your query
select
mt.master_id,
mt.user_name,
max (case when mmt.meta_key = 'f_name' then mmt.meta_value end) as fname,
max (case when mmt.meta_key = 'l_name' then mmt.meta_value end) as lname,
max (case when mmt.meta_key = 'age' then mmt.meta_value end) as age,
max (case when mmt.meta_key = 'sex' then mmt.meta_value end) as sex
from
master_table mt,master_meta_table mmt
where mt.master_id = mmt.master_id
group by mt.master_id,mt.user_name
http://sqlfiddle.com/#!4/55845/8