convert Rows to column - sql-server-2008

Looking for the way to change row to column. (The comflag is of type bit and not null). Help appreciated
Table1
Id Commflag value
122 0 Ce
125 1 Cf
122 0 Cg
125 1 cs
Here is what I want in result
id ce cf cg cs cp
122 0 null 0 null null
125 null 1 null 1 null
The below query shows error-
SELECT ID , [CE],[CF],[CG],[CS],[CP]
FROM TABLE1
PIVOT ((convert((Commflag)as varchar()) FOR value IN [CE],[CF],[CG],[CS],[CP] as pvt
ORDER BY date

This query does what you want:
select Id, pvt.Ce, pvt.Cf, pvt.CG, pvt.Cs, pvt.Cp
from
(
select Id, cast(Commflag as tinyint) Commflag, value
from Table1
) t
pivot (max(Commflag) for value in ([Ce],[Cf],[CG],[Cs],[Cp])) pvt
SQL Fiddle
Here's another way to do it, without using PIVOT:
select Id,
max(case value when 'Ce' then CAST(Commflag as tinyint) else null end) Ce,
max(case value when 'Cf' then CAST(Commflag as tinyint) else null end) Cf,
max(case value when 'Cg' then CAST(Commflag as tinyint) else null end) Cg,
max(case value when 'Cs' then CAST(Commflag as tinyint) else null end) Cs,
max(case value when 'Cp' then CAST(Commflag as tinyint) else null end) Cp
from Table1
group by Id
order by Id
SQL Fiddle

Related

Can you join a table with another table you are pivoting on a field you are creating with the pivot?

I have a table I need to pivot that contains a value I need to join with a field in another table. I'm trying to determine if I can do this in one step, or if I need to pivot the first table and then join them together. GROUP_ID is in field_name in the redcap_data table and needs to be joined with group_id in redcap_data_access_groups.
CREATE VIEW vwGlobalHealthInfants AS
SELECT rd.record as record_id,
MAX(CASE WHEN rd.field_name = '__GROUP_ID__' THEN rd.value ELSE NULL END) as GroupId,
g.group_name as hospno,
MAX(CASE WHEN rd.field_name = 'admission_temperature' THEN rd.value ELSE NULL END) as adtemp,
MAX(CASE WHEN rd.field_name = 'antenatal_care' THEN rd.value ELSE NULL END) as antecare,
MAX(CASE WHEN rd.field_name = 'anti_hypertensive' THEN rd.value ELSE NULL END) as antihyper,
MAX(CASE WHEN rd.field_name = 'anticonvulsants' THEN rd.value ELSE NULL END) as anticonvul
FROM (
redcapVON.redcap_data rd
JOIN redcapVON.redcap_data_access_groups g ON ( (
GroupId = g.group_id
) )
)
WHERE (
rd.project_id = 12
)
GROUP BY rd.record
I don't know if it's possible to get it to recognize the GroupID field in the join before the pivot.
CTE would solve it. We just don't have the most updated version of mysql to run it. 2 steps it is.

MySQL - Rows to Columns and keeps NULL

We have the following table (TEST2) in the MySQL database (MySQL 5.6):
TEAM_ID,MEMBER_ID,TYPE,SCORE
1,2,A,150
1,3,B,200
1,1,B,50
1,1,A,100
1,2,B,NULL
We try to transform/pivot the above table based on the TYPE column:
If the TYPE column has value == A, move the value in the SCORE column into a new column called A_SCORE. If the value in the SCORE column is NULL, it should show NULL in the new A_SCORE column.
If the TYPE column has value == B, move the value in the SCORE column into a new column called B_SCORE. If the value in the SCORE column is NULL, it should show NULL in the new B_SCORE column.
The following table is the one we are looking for (the wanted table):
TEAM_ID,MEMBER_ID,A_SCORE,B_SCORE,A_SCORE_MINUS_B_SCORE
1,1,100,50,50
1,2,150,NULL,NULL
1,3,0,200,-200
We tried the following query
SELECT TEAM_ID,MEMBER_ID,A_SCORE,B_SCORE,SUM(A_SCORE-B_SCORE) AS ACTUAL_MINUS_B_SCORE FROM
(SELECT TEAM_ID,MEMBER_ID,
CASE
WHEN SCORE IS NULL
THEN NULL
ELSE SUM(if(TYPE = 'A', SCORE,0) )
END A_SCORE,
CASE
WHEN SCORE IS NULL
THEN NULL
ELSE SUM(if(TYPE = 'B', SCORE,0) )
END B_SCORE
FROM TEST2
GROUP BY TEAM_ID,MEMBER_ID,SCORE) AS A
GROUP BY TEAM_ID,MEMBER_ID,A_SCORE,B_SCORE);
It returns something we don’t want:
TEAM_ID,MEMBER_ID,A_SCORE,B_SCORE,A_SCORE_MINUS_B_SCORE
1,1,0,50,-50
1,1,100,0,100
1,2,0,0,0
1,2,150,0,150
1,3,0,200,-200
If we tried the following, it generates a table close to what we want, but it doesn’t return any NULL value.
SELECT TEAM_ID,MEMBER_ID,A_SCORE,B_SCORE,SUM(A_SCORE-B_SCORE) AS A_SCORE _MINUS_B_SCORE FROM
(SELECT TEAM_ID,MEMBER_ID,
SUM(if(TYPE = 'A', SCORE,0) ) AS A_SCORE,
SUM(if(TYPE = 'B', SCORE,0) )AS B_SCORE
FROM TEST2
GROUP BY TEAM_ID,MEMBER_ID) AS A
GROUP BY TEAM_ID,MEMBER_ID,A_SCORE,B_SCORE;
The result of the above query:
TEAM_ID,MEMBER_ID,A_SCORE,B_SCORE,A_SCORE_MINUS_B_SCORE
1,1,100,50,50
1,2,150,0,0
1,3,0,200,-200
Could any guru enlighten how to generate the wanted table in this case using MySQL? The SQL fiddle is here for your convenience.
http://sqlfiddle.com/#!9/cfe7a1/1
Thanks!
Try this;)
SELECT TEAM_ID, MEMBER_ID, A_SCORE, B_SCORE, A_SCORE - B_SCORE AS A_SCORE_MINUS_B_SCORE
FROM (
SELECT
TEAM_ID, MEMBER_ID,
CASE
WHEN A_SCORE IS NULL AND NOT EXISTS (
SELECT 1 FROM TEST2
WHERE TEAM_ID = T1.TEAM_ID
AND MEMBER_ID = T1.MEMBER_ID
AND TYPE = 'A'
) THEN 0 ELSE A_SCORE END AS A_SCORE,
CASE
WHEN B_SCORE IS NULL AND NOT EXISTS (
SELECT 1 FROM TEST2
WHERE TEAM_ID = T1.TEAM_ID
AND MEMBER_ID = T1.MEMBER_ID
AND TYPE = 'A'
) THEN 0 ELSE B_SCORE END AS B_SCORE
FROM (
SELECT
TEAM_ID, MEMBER_ID,
MAX(CASE WHEN TYPE = 'A' THEN SCORE END) AS A_SCORE,
MAX(CASE WHEN TYPE = 'B' THEN SCORE END) AS B_SCORE
FROM TEST2
GROUP BY TEAM_ID, MEMBER_ID
) T1
)T
SQLFiddle demo here
I don't quite understand the calculation criteria, but something like this should work...
SELECT team_id
, member_id
, COALESCE(MAX(CASE WHEN type = 'A' THEN score END),0) a_score
, COALESCE(MAX(CASE WHEN type = 'B' THEN score END),0) b_score
, COALESCE(MAX(CASE WHEN type = 'A' THEN score END),0)
- COALESCE(MAX(CASE WHEN type = 'B' THEN score END),0) diff
FROM test2
GROUP
BY team_id
, member_id;

MySql, Postgres, Oracle and SQLServer ignoring IS NOT NULL filter

While I was preparing an answer to one of our fellows here on SO I've encounter an odd situation, at least to me. The original question is here: Pivot Table Omitting Rows that Have Null values
I've modified the query to use max instead of group_concat in order to show the "problem" in all databases.
SELECT
id,
max(case when colID = 1 then value else '' end) AS fn,
max(case when colID = 2 then value else '' end) AS ln,
max(case when colID = 3 then value else '' end) AS jt
FROM tbl
GROUP BY id
The result of this query is this:
ID FN LN JT
1 Sampo Kallinen Office Manager
2 Jakko Salovaara Vice President
3 (null) Foo No First Name
The user asks to filter the row with id 3 because the field value is null.
When it seems pretty obvious that only it needs to do was to add a WHERE value IS NOT NULL constraint on that query to achieve what the user expect. It won't work.
So I start to test it on the other databases to see what happens (Queries with the WHERE CLAUSE)
SELECT
id,
max(case when colID = 1 then value else '' end) AS fn,
max(case when colID = 2 then value else '' end) AS ln,
max(case when colID = 3 then value else '' end) AS jt
FROM tbl
WHERE value is not null
GROUP BY id
Mysql: http://sqlfiddle.com/#!2/78395/1
Postgres: http://sqlfiddle.com/#!15/78395/1
SQLServer: http://sqlfiddle.com/#!6/78395/1
Oracle: http://sqlfiddle.com/#!4/78395/1
For my surprise the result was the same, none worked.
Then I tried a different version of the same query:
SELECT * FROM (
SELECT
id,
max(case when colID = 1 then value else '' end) AS fn,
max(case when colID = 2 then value else '' end) AS ln,
max(case when colID = 3 then value else '' end) AS jt
FROM tbl
GROUP BY id
) T
WHERE fn IS NOT NULL
AND ln IS NOT NULL
AND jt IS NOT NULL
Oracle: http://sqlfiddle.com/#!4/78395/2 WORKED
MySql: http://sqlfiddle.com/#!2/78395/2
Postgres: http://sqlfiddle.com/#!15/78395/2
SQLServer: http://sqlfiddle.com/#!6/78395/2
The only way I could make it work on all databases was with this query:
SELECT
id,
max(case when colID = 1 then value else '' end) AS fn,
max(case when colID = 2 then value else '' end) AS ln,
max(case when colID = 3 then value else '' end) AS jt
FROM tbl
WHERE NOT EXISTS (SELECT * FROM tbl b WHERE tbl.id=b.id AND value IS NULL)
GROUP BY id
So I ask:
What is happening here that except for that specific case on Oracle all other DBs seem to ignore the IS NOT NULL filter?
To omit the row from the result if any of the source rows for the same id has value IS NULL, a solution in Postgres would be to use the aggregate function every() or (synonym for historical reasons) bool_and() in the HAVING clause:
SELECT id
, max(case when colID = 1 then value else '' end) AS fn
, max(case when colID = 2 then value else '' end) AS ln
, max(case when colID = 3 then value else '' end) AS jt
FROM tbl
GROUP BY id
HAVING every(value IS NOT NULL);
SQL Fiddle.
Explain
Your attempt with a WHERE clause would just eliminate one source row for id = 3 in your example (the one with colID = 1), leaving two more for the same id. So we still get a row for id = 3 in the result after aggregating.
But since we have no row with colID = 1, we get an empty string (note: not a NULL value!) for fn in the result for id = 3.
A faster solution in Postgres would be to use crosstab(). Details:
PostgreSQL Crosstab Query
Other RDBMS
While EVERY is defined in the SQL:2008 standard, many RDBMS do not support it, presumably because some of them have shady implementations of the boolean type. (Not dropping any names like "MySQL" or "Oracle" ...). You can probably substitute everywhere (including Postgres) with:
SELECT id
, max(case when colID = 1 then value else '' end) AS fn
, max(case when colID = 2 then value else '' end) AS ln
, max(case when colID = 3 then value else '' end) AS jt
FROM tbl
GROUP BY id
HAVING count(*) = count(value);
Because count() doesn't count NULL values. In MySQL there is also bit_and().
More under this related question:
Is there any equivalent to Postgresql EVERY aggregate function on other RDBMS?
It works in Oracle because Oracle handles NULL incorrectly in that NULL and '' are the same. The other databases don't do this because it is wrong. NULL is unknown, versus '' which is just a blank, empty string.
So if your where clause said something like WHERE (fn IS NOT NULL or fn <> '') you would probably get further.
I think this is a case where a HAVING clause will do what you need.
SELECT id, max ... (same stuff as before)
FROM tbl
GROUP by id
HAVING fn IS NOT NULL
AND ln IS NOT NULL
AND jt IS NOT NULL

Best way to index and query analytic table in MySQL

I have an analytics table (5M rows and growing) with the following structure
Hits
id int() NOT NULL AUTO_INCREMENT,
hit_date datetime NOT NULL,
hit_day int(11) DEFAULT NULL,
gender varchar(255) DEFAULT NULL,
age_range_id int(11) DEFAULT NULL,
klout_range_id int(11) DEFAULT NULL,
frequency int(11) DEFAULT NULL,
count int(11) DEFAULT NULL,
location_id int(11) DEFAULT NULL,
source_id int(11) DEFAULT NULL,
target_id int(11) DEFAULT NULL,
Most queries to the table is to query between two datetimes for a particular sub-set of columns and them sum up all the count column across all rows. For example:
SELECT target.id,
SUM(CASE gender WHEN 'm' THEN count END) AS 'gender_male',
SUM(CASE gender WHEN 'f' THEN count END) AS 'gender_female',
SUM(CASE age_range_id WHEN 1 THEN count END) AS 'age_18 - 20',
SUM(CASE target_id WHEN 1 then count END) AS 'target_test'
SUM(CASE location_id WHEN 1 then count END) AS 'location_NY'
FROM Hits
WHERE (location_id =1 or location_id = 2)
AND (target_id = 40 OR target_id = 22)
AND cast(hit_date AS date) BETWEEN '2012-5-4'AND '2012-5-10'
GROUP BY target.id
The interesting thing about queries to this table is that the where clause include any permutation of Hit columns names and values since those are what we're filtering against. So the particular query above is getting the # of males and females between the ages of 18 and 20 (age_range_id 1) in NY that belongs to a target called "test". However, there are over 8 age groups, 10 klout ranges, 45 locations, 10 sources etc (all
foreign key references).
I currently have an index on hot_date and another one on target_id. What the best way to properly index this table?. Having a composite index on all column fields seems inherently wrong.
Is there any other way to run this query without using a sub-query to sum up all counts? I did some research and this seems to be the best way to get the data-set I need but is there a more efficient way of handling this query?
Here's your optimized query. The idea is to get rid of the ORs and the CAST() function on hit_date so that MySQL can utilize a compound index that covers each of the subsets of data. You'll want a compound index on (location_id, target_id, hit_date) in that order.
SELECT id, gender_male, gender_female, `age_18 - 20`, target_test, location_NY
FROM
(
SELECT target.id,
SUM(CASE gender WHEN 'm' THEN 1 END) AS gender_male,
SUM(CASE gender WHEN 'f' THEN 1 END) AS gender_female,
SUM(CASE age_range_id WHEN 1 THEN 1 END) AS `age_18 - 20`,
SUM(CASE target_id WHEN 1 then 1 END) AS target_test,
SUM(CASE location_id WHEN 1 then 1 END) AS location_NY
FROM Hits
WHERE (location_id =1)
AND (target_id = 40)
AND hit_date BETWEEN '2012-05-04 00:00:00' AND '2012-05-10 23:59:59'
GROUP BY target.id
UNION ALL
SELECT target.id,
SUM(CASE gender WHEN 'm' THEN 1 END) AS gender_male,
SUM(CASE gender WHEN 'f' THEN 1 END) AS gender_female,
SUM(CASE age_range_id WHEN 1 THEN 1 END) AS `age_18 - 20`,
SUM(CASE target_id WHEN 1 then 1 END) AS target_test,
SUM(CASE location_id WHEN 1 then 1 END) AS location_NY
FROM Hits
WHERE (location_id = 2)
AND (target_id = 22)
AND hit_date BETWEEN '2012-05-04 00:00:00' AND '2012-05-10 23:59:59'
GROUP BY target.id
UNION ALL
SELECT target.id,
SUM(CASE gender WHEN 'm' THEN 1 END) AS gender_male,
SUM(CASE gender WHEN 'f' THEN 1 END) AS gender_female,
SUM(CASE age_range_id WHEN 1 THEN 1 END) AS `age_18 - 20`,
SUM(CASE target_id WHEN 1 then 1 END) AS target_test,
SUM(CASE location_id WHEN 1 then 1 END) AS location_NY
FROM Hits
WHERE (location_id =1)
AND (target_id = 22)
AND hit_date BETWEEN '2012-05-04 00:00:00' AND '2012-05-10 23:59:59'
GROUP BY target.id
UNION ALL
SELECT target.id,
SUM(CASE gender WHEN 'm' THEN 1 END) AS gender_male,
SUM(CASE gender WHEN 'f' THEN 1 END) AS gender_female,
SUM(CASE age_range_id WHEN 1 THEN 1 END) AS `age_18 - 20`,
SUM(CASE target_id WHEN 1 then 1 END) AS target_test,
SUM(CASE location_id WHEN 1 then 1 END) AS location_NY
FROM Hits
WHERE (location_id = 2)
AND (target_id = 22)
AND hit_date BETWEEN '2012-05-04 00:00:00' AND '2012-05-10 23:59:59'
GROUP BY target.id
) a
GROUP BY id
If your selection size is so large that this is no improvement, then you may as well keep scanning all rows like you're already doing.
Note, surround aliases with back ticks, not single quotes, which are deprecated. I also fixed your CASE clauses which had count instead of 1.

MySql: Displaying Sums of all rows for each column as an extra row at the end

How do I get the sum of each column for all rows of a result-set? I mean I want to display the sums-row as the last row of my result-set.
My query looks like this:
select f.filename,
count(distinct case when v.rUser like '%bike%' then 1 else null end) as bikeUser,
count(distinct case when v.rUser like '%Pedestrian%' then 1 else null end) as pedestrianUser,
count(distinct case when d.weather like '%clear%' then 1 else null end) as clearWeather,
count(case when m.extras like '%hat%' then 1 else null end) as hatExtras
from VMdata v
inner join files f on v.id = f.id
inner join DMdata d on f.id = d.id
inner join MultiFiledata m on f.id = m.id
where f.filename in (X,Y,Z) group by f.filename;
When I use with roll up after the 'group by' clause, it gives me sum of the groups generated by the 'group by clause' (horizontal sum) whereas I need the vertical sum of each column at the end.
Any ideas?
Your ROLLUP is already correct, it's really the COUNT(CASE WHEN Field = 'Blah' THEN 1 ELSE 0 END) is the main culprit why your query is not working
You must do either:
COUNT(CASE WHEN Field = 'Blah' THEN 1 END)
or
SUM(CASE WHEN Field = 'Blah' THEN 1 ELSE 0 END)
But since MySQL has a duality between boolean and integer type like it is in C language, hence you can do this too:
SUM(Field = 'Blah')
This is your incorrect query (wrong results): http://www.sqlfiddle.com/#!2/70187/1
create table ProductInventory(
ProductCode varchar(10) not null,
Location varchar(50) not null
);
insert into ProductInventory(ProductCode,Location) values('CPU','US');
insert into ProductInventory(ProductCode,Location) values('CPU','US');
insert into ProductInventory(ProductCode,Location) values('CPU','CN');
insert into ProductInventory(ProductCode,Location) values('KB','CN');
insert into ProductInventory(ProductCode,Location) values('KB','JP');
insert into ProductInventory(ProductCode,Location) values('KB','US');
insert into ProductInventory(ProductCode,Location) values('MOUSE','US');
insert into ProductInventory(ProductCode,Location) values('MOUSE','CN');
Incorrect Output:
PRODUCTCODE USQTY CHINAQTY
CPU 3 3
KB 3 3
MOUSE 2 2
8 8
This is the correct query: http://www.sqlfiddle.com/#!2/70187/2
select ProductCode,
COUNT(CASE WHEN Location = 'US' THEN 1 END) as UsQty,
COUNT(CASE WHEN Location = 'CN' THEN 1 END) as ChinaQty
from ProductInventory
group by ProductCode with rollup
Correct output:
PRODUCTCODE USQTY CHINAQTY
CPU 2 1
KB 1 1
MOUSE 1 1
4 3
Please, don't insist that this is correct, this is very incorrect:
COUNT(CASE WHEN Location = 'US' THEN 1 ELSE 0 END) AS UsQty
You must either do this (correct) :
COUNT(CASE WHEN Location = 'US' THEN 1 END) AS UsQty
Or this (correct) : http://www.sqlfiddle.com/#!2/70187/5
SUM(CASE WHEN Location = 'US' THEN 1 ELSE 0 END) AS UsQty
Or this (correct) : http://www.sqlfiddle.com/#!2/70187/6
SUM(CASE WHEN Location = 'US' THEN 1 END) AS UsQty
Or try take advantage of the fact that MySql has duality between boolean and integer (correct) : http://www.sqlfiddle.com/#!2/70187/4
SUM(Location = 'US') AS UsQty
Bottomline
Please don't use this (incorrect) : http://www.sqlfiddle.com/#!2/70187/3
COUNT(Location = 'US') as UsQty
And please don't use this too (incorrect, similar to your query): http://www.sqlfiddle.com/#!2/70187/1
COUNT(CASE WHEN Location = 'US' THEN 1 ELSE 0 END) as UsQty
By the way, this also works, it's for you to find out why ;-)
COUNT(CASE WHEN Location = 'US' THEN 1976 END) AS UsQty
UPDATE
I have an inkling that this is what you need:
create table Product
(
ProductCode varchar(10) not null primary key,
ProductName varchar(100) not null
);
insert into Product(ProductCode,ProductName) values
('CPU','Central Processing Unit'),
('KB','Keyboard'),
('MSE','Mouse'),
('RAM', 'Random Access Memory');
create table ProductInventory(
ProductCode varchar(10) not null,
Location varchar(50) not null
);
insert into ProductInventory(ProductCode,Location) values
('CPU','US'),
('CPU','PH'),
('CPU','PH'),
('KB','PH'),
('KB','US'),
('KB','US'),
('MSE','US'),
('MSE','JP');
select p.ProductCode,
coalesce(SUM(i.Location = 'US'),0) as UsQty,
coalesce(SUM(i.Location = 'PH'),0) as PhilippinesQty
from Product p
left join ProductInventory i on i.ProductCode = p.ProductCode
group by p.ProductCode with rollup
Output:
ProductCode UsQty PhilippinesQty
CPU 1 2
KB 2 1
MSE 1 0
RAM 0 0
4 4
Live test: http://www.sqlfiddle.com/#!2/2bb09/1
Don't use COUNT for counting when you are using evaluation; despite the name, SUM would yield the correct result for counting based on conditions:
Given this: http://www.sqlfiddle.com/#!2/79375/1
create table ProductInventory(
ProductCode varchar(10) not null,
Location varchar(50) not null
);
insert into ProductInventory(ProductCode,Location) values('CPU','US');
insert into ProductInventory(ProductCode,Location) values('CPU','US');
insert into ProductInventory(ProductCode,Location) values('CPU','ARM');
insert into ProductInventory(ProductCode,Location) values('KB','CN');
insert into ProductInventory(ProductCode,Location) values('KB','PH');
insert into ProductInventory(ProductCode,Location) values('KB','US');
insert into ProductInventory(ProductCode,Location) values('MOUSE','AA');
insert into ProductInventory(ProductCode,Location) values('MOUSE','BB');
select ProductCode, COUNT(CASE WHEN Location = 'US' THEN 1 ELSE 0 END) as Qty
from ProductInventory
group by ProductCode
order by ProductCode
That will produce incorrect results:
PRODUCTCODE QTY
CPU 3
KB 3
MOUSE 2
Use SUM instead, correct results: http://www.sqlfiddle.com/#!2/79375/3
select ProductCode, SUM(Location = 'US') as Qty
from ProductInventory
group by ProductCode
order by ProductCode
That would result to:
PRODUCTCODE QTY
CPU 2
KB 1
MOUSE 0
COUNT works by counting the NON-nullness of value or expression
If you still want to use COUNT, pass any non-null value to COUNT; and don't use ELSE NULL END, your query will look tedious, just saying :-) http://www.sqlfiddle.com/#!2/79375/4
select ProductCode, COUNT(CASE WHEN Location = 'US' THEN Location END) as Qty
from ProductInventory
group by ProductCode
order by ProductCode
Output:
PRODUCTCODE QTY
CPU 2
KB 1
MOUSE 0
You can create a temptable (#mytemptable) and add the sum as last entry and then return the select of the created temptable. But this is only working in stored procedures I think.
select f.filename,
count(case when v.rUser like '%bike%' then 1 else 0 end) as bikeUser,
count(case when v.rUser like '%Pedestrian%' then 1 else 0 end) as pedestrianUser,
count(case when d.weather like '%clear%' then 1 else 0 end) as clearWeather,
count(case when m.extras like '%hat%' then 1 else 0 end) as hatExtras
INTO #myTempTable from VMdata v
inner join files f on v.id = f.id
inner join DMdata d on f.id = d.id
inner join MultiFiledata m on f.id = m.id
where f.filename in (X,Y,Z) group by f.filename;
INSERT INTO #myTempTable select(create the sum here but care that you have the same columns)
SELECT * FROM #myTempTable
within just one select you can do it with the command "UNION"
*EDITED: 27.04. 11:55
select f.filename,
count(case when v.rUser like '%bike%' then 1 else 0 end) as bikeUser,
count(case when v.rUser like '%Pedestrian%' then 1 else 0 end) as pedestrianUser,
count(case when d.weather like '%clear%' then 1 else 0 end) as clearWeather,
count(case when m.extras like '%hat%' then 1 else 0 end) as hatExtras
from VMdata v
inner join files f on v.id = f.id
inner join DMdata d on f.id = d.id
inner join MultiFiledata m on f.id = m.id
where f.filename in (X,Y,Z) group by f.filename;
UNION
SELECT SUM(bikeUser), SUM(pedestrianUser), SUM(clearWeather), SUM(hatExtras)
FROM (
select f.filename,
count(case when v.rUser like '%bike%' then 1 else 0 end) as bikeUser,
count(case when v.rUser like '%Pedestrian%' then 1 else 0 end) as pedestrianUser,
count(case when d.weather like '%clear%' then 1 else 0 end) as clearWeather,
count(case when m.extras like '%hat%' then 1 else 0 end) as hatExtras
from VMdata v
inner join files f on v.id = f.id
inner join DMdata d on f.id = d.id
inner join MultiFiledata m on f.id = m.id
where f.filename in (X,Y,Z) group by f.filename) as summary
hope this helps :)