How to retrieve data from multiple daily tables in SQL Server - sql

I am new to Microsoft SQL Server 2008. I need some help in retrieving data from multiple tables which have same columns with same datatype.
Currently I have multiple tables in my database, each table contains data for a single day. For example, I have the following tables:
Table_20160820
Table_20160821
Table_20160822
Table_20160823
Table_20160824
Table_20160825
All the tables have same columns with same datatype say:
column_1
column_2
column_3
column_4
Now, is it possible to retrieve the columns from all the tables using a single query.
What I am exactly looking for is to get the count of column_3 which will be grouped by column_1 for all the tables. I want to avoid writing multiple queries as I need to fetch the data for an entire month i.e. from 30 tables.

As the comments have said, it'd be best to organize this into a single table, and then add a date column so you can see when each row was added. You can even set the default value of the date_created column to be getdate().
To get all of the data together use the UNION Operator in conjunction with an insert statement to your new better table.
CREATE TABLE Better_Table (Column_1 <type>, Column_2 <type>, ..., Date_Created DateTime2(7) Default GETDATE())
GO
INSERT INTO Better_Table (Column_1, Column_2, ...)
SELECT *, '2016/08/22' FROM Table_20160822
UNION
SELECT *, '2016/08/23' FROM Table_20160823
...
Once you've done this your query will be far simpler:
SELECT Column_1, COUNT(Column_3)
FROM Better_Table
WHERE date_created >= '2016/08/01'
AND date_created < '2016/09/01'
GROUP BY Column_1
Although you can still do this in the db current state by using the union operator in the group by query. It would look something like this:
SELECT a.column_1, COUNT(a.column_3)
FROM (
SELECT column_1, Column_3
FROM Table_20160822
UNION ALL
SELECT column_1, Column_3
FROM Table_20160823
) a
GROUP BY a.Column_1
Just expand this to the tables you need to grab from.

You can use CTE to get all dates you need, then create a query and execute it:
DECLARE #dateStart datetime = '2016-08-01',
#dateFinish datetime = '2016-09-01',
#query nvarchar(max)
;WITH cte as (
SELECT #dateStart as d
UNION ALL
SELECT DATEADD(day,1,d)
FROM cte
WHERE DATEADD(day,1,d) < #dateFinish
)
SELECT #query = (
SELECT 'SELECT column_1, COUNT(column_3) FROM ( '
+ STUFF((
SELECT ' UNION ALL SELECT * FROM [Table_'+CONVERT(nvarchar(8),d,112)+'] '
FROM cte
FOR XML PATH('')
),1,10,'') + ') as t GROUP BY column_1 '
FOR XML PATH('')
)
PRINT #query
EXEC sp_executesql #query
Output of #query variable:
SELECT column_1, COUNT(column_3)
FROM (
SELECT * FROM [Table_20160801] UNION ALL
SELECT * FROM [Table_20160802] UNION ALL
SELECT * FROM [Table_20160803] UNION ALL
SELECT * FROM [Table_20160804] UNION ALL
....
SELECT * FROM [Table_20160831]
) as t
GROUP BY column_1

As mentioned above this is a bad design and it would be good if the design is fixed at first place. This is a technical debt which has to be paid back sooner or later. Anyway here's how you can do it:
DECLARE #dtStartDate DATE,
#dtEndDate DATE,
#nvchTablePrefix NVARCHAR(50),
#nvchQuery NVARCHAR(max)
SELECT #dtStartDate = '20160801',
#dtEndDate = '20160831',
#nvchTablePrefix = 'Table_'
CREATE TABLE #temp
(name NVARCHAR(100))
WHILE(#dtStartDate <= #dtEndDate)
BEGIN
INSERT INTO #temp
SELECT ' SELECT column_1, column_3 FROM ' + #nvchTablePrefix + CONVERT(NVARCHAR,#dtStartDate,112)
SELECT #dtStartDate = DATEADD(d,1,#dtStartDate)
IF (#dtStartDate <= #dtEndDate)
INSERT INTO #temp
SELECT ' UNION '
END
SELECT #nvchQuery = 'SELECT column_1, COUNT(column_3) as column3count FROM ( '
SELECT #nvchQuery = #nvchQuery + name FROM #temp
SELECT #nvchQuery = #nvchQuery + ') t GROUP BY column1'
PRINT #nvchQuery
EXEC sp_executesql #nvchQuery
DROP TABLE #temp
OUTPUT of print statement will be like -
SELECT column_1, COUNT(column_3) as column3count
FROM
( SELECT column_1, column_3 FROM Table_20160801
UNION
SELECT column_1, column_3 FROM Table_20160802
UNION
....
UNION
SELECT column_1, column_3 FROM Table_20160831
) t GROUP BY column1

Related

How to dynamically convert rows to columns in SQL Server

I want to convert rows to columns dynamically, for sample data I have given below query.
create table testtable
(
tableid int primary key identity(1,1),
tableDatetime datetime,
names varchar(50),
tablevalue decimal(18,9)
)
go
insert into testtable
select '2019-06-13 13:56:39.117', 'test1',23.45 union all
select '2019-06-13 13:56:39.117', 'test2',33.45 union all
select '2019-06-13 13:56:39.117', 'test3',10.45 union all
select '2019-06-13 13:56:39.117', 'test4',90.45 union all
select '2019-06-13 14:01:41.280', 'test1',33.45 union all
select '2019-06-13 14:01:41.280', 'test2',53.45 union all
select '2019-06-13 14:01:41.280', 'test3',41.45 union all
select '2019-06-13 14:01:41.280', 'test4',93.45 union all
select '2019-06-13 14:06:42.363', 'test1',30.45 union all
select '2019-06-13 14:06:42.363', 'test2',13.45 union all
select '2019-06-13 14:06:42.363', 'test3',23.45 union all
select '2019-06-13 14:06:42.363', 'test4',73.45
go
select * from testtable
I want to convert data in attached image format
Thanks,
You may try dynamic sql query as per your table structure.
GO
declare #query varchar(max)
set #query = (select stuff( (select distinct ',' + names from testtable for xml path ('')) ,1,1,'') as d)
declare #resquery nvarchar(max)
set #resquery = '
select * from (
select tableDatetime , names , tablevalue from testtable
) as d
pivot ( max(tablevalue) for names in ( ' + #query + ' ) ) as pv'
exec sp_executesql #resquery
GO
Please use this as per your table structure, this will create dynamic column names for your current table data. Which is further use in pivot to convert your rows into columns.
Mark it as accepted, or comment for further query.

Getting Unique values from a row - SQL Server

I have columns something like this:
col1 | col2 | col3 | col4 | col5 | col6 |
-----+------+------+------+------+------+
a | b | c | a | c | c
I am trying to get unique values in the column it self PER row.
So ideally, I want a,b,c to be returned
I tried doing PIVOT and applying a DISTINCT but that doesn't go well as there are other columns that I couldn't show in the question.
So is there another way that this could be obtained?
Thanks in advance
Is this what you are looking for ..?
IF OBJECT_ID('tempdb..#Pivot_data')IS NOT NULL
DROP TABLE #Pivot_data
IF OBJECT_ID('tempdb..#tab')IS NOT NULL
DROP TABLE #tab
select * into #tab from
(select 'a'AS COL1,'b'AS COL2,'c'AS COL3,'a'AS COL4,'c'AS COL5,'c' COL6)AS A
DECLARE #Columns nvarchar(max) ,#QUERY NVARCHAR(MAX)
;WITH CTE AS (
SELECT COLUMNSS,COL_VALUES,ROW_NUMBER()OVER(PARTITION BY COL_VALUES ORDER BY (SELECT 1))RN FROM (
SELECT * FROM #tab
)AS A
UNPIVOT(COL_VALUES FOR COLUMNSS IN([col1],[col2],[col3],[col4],[col5],[col6])) AS B
)
,FINAL_Result as (select COLUMNSS,COL_VALUES from CTE where RN=1)
SELECT * INTO #Pivot_data FROM FINAL_Result
SET #Columns= (SELECT STUFF((SELECT ',['+COLUMNSS+']' FROM #Pivot_data FOR XML PATH('')),1,1,''))
SET #QUERY=N'SELECT * FROM (
SELECT * FROM #Pivot_data
) AS A
PIVOT (MAX(COL_VALUES)FOR COLUMNSS IN('+#Columns+'))
AS B'
PRINT #QUERY
EXEC (#QUERY)
Logic :
From the given table i did unpivot and generated a Row_number() based on the column values and considered only which are Row_num=1 i.e Distinct columns values . and finally, i Pivoted the resultant data .
It seems to be CROSS APPLY would be work here
select a.Col from table t
cross apply (
values (t.Col1), (t.Col2), (t.Col3),
(t.Col4), (t.Col5), (t.Col6)
)a(Col)
group by a.Col
AND, do the PIVOT with your own way
Try this code
IF OBJECT_ID('tempdb..#Temptab')IS NOT NULL
DROP TABLE #Temptab
;With cte(col1 , col2 , col3 , col4 , col5 , col6 )
AS
(
SELECT 'a' , 'b' , 'c' , 'a' , 'c' , 'c'
)
SELECT DISTINCT AllColumn
INTO #Temptab FROM cte
CROSS APPLY ( VALUES (col1),( col2) , (col3) , (col4) , (col5) , (col6)
) AS A (AllColumn)
DECLARE #SqlQuery nvarchar(max)
,#Sql nvarchar(max)
SELECT #SqlQuery='SELECT DISTINCT '+STUFF((SELECT ', '+ReqColumn FROM
(
SELECT ''''+AllColumn +'''' +' AS Col'+ CAST(Seq AS VARCHAR(2)) As ReqColumn
FROm
(
SELECT ROW_NUMBER()OVER(Order by AllColumn) AS Seq,AllColumn FROM #Temptab
)dt
)dte FOR XML PATH ('')),1,1,'') +' From #Temptab'
PRINT #SqlQuery
EXEC(#SqlQuery)
Result
Col1 Col2 Col3
----------------------
a b c
You can first union all columns to get unique values and then use the GROUP_CONCAT() function in MySql or if your database is Oracle then use list_agg() function:
Please try the below SQL:
select GROUP_CONCAT(col1 SEPARATOR ', ') from (
select '1' as 'serial', col1 from pivot
union
select '1' as 'serial',col2 from pivot
union
select '1' as 'serial',col3 from pivot
union
select '1' as 'serial',col4 from pivot
union
select '1' as 'serial',col5 from pivot
union
select '1' as 'serial' ,col6 from pivot
)derived
GROUP BY serial;
Output:
Note : I have make the 'serial' column in my query to do the group by. You can use the your identifier field in group by clause if you have any.

how to create a table structure from column values of another table in MSSQL

I have a scenario where i have the entries in a column of a table with CSV ( these are dynamic values). I need to generate the tables with those values in sqlserver(MSSQL)
Input Table
Value
FirstName,LastName,SSN
Address1,City,Zip
HomePhone,CellPhone
Output Table1
FirstName LastName SSN
Output Table2
Address1 City Zip
Output Table3
HomePhone CellPhone
Can some one please help me.
You need dynamic SQL for this, such as:
declare #sql nvarchar(max);
with t as (
select 'FirstName,LastName,SSN' as value union all
select 'Address1,City,Zip' union all
select 'HomePhone,CellPhone'
)
select #sql = (select 'create table'+CAST(seqnum as varchar(255))+' ('+REPLACE(value, ',', ' varchar(255),') + ' varchar(255)); '
from (select t.*, ROW_NUMBER() over (order by (select null)) as seqnum
from t
) t
for xml path ('')
)
exec sp_executesql #sql;
Try This,
Select FirstName,LastName,SSN into Table1 from #InputTable
Select Address1,City,Zip into Table2 from #InputTable
Select HomePhone,CellPhone into Table1 from #InputTable

SQL query problem

Let´s say I have two tables, "Garden" and "Flowers". There is a 1:n-relationship between these tables, because in a garden can be many flowers. Is it possible to write an SQL query which returns a result with the following structure:
GardenName Flower1Name Flower2Name .... (as long as there are entries in flowers)
myGarden rose tulip
CREATE TABLE #Garden (Id INT, Name VARCHAR(20))
INSERT INTO #Garden
SELECT 1, 'myGarden' UNION ALL
SELECT 2, 'yourGarden'
CREATE TABLE #Flowers (GardenId INT, Flower VARCHAR(20))
INSERT INTO #Flowers
SELECT 1, 'rose' UNION ALL
SELECT 1, 'tulip' UNION ALL
SELECT 2, 'thistle'
DECLARE #ColList nvarchar(max)
SELECT #ColList = ISNULL(#ColList + ',','') + QUOTENAME('Flower' + CAST(ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS VARCHAR))
FROM #Flowers WHERE GardenId = (
SELECT TOP 1 GardenId
FROM #Flowers
ORDER BY COUNT(*) OVER (PARTITION BY GardenId) DESC
)
EXEC (N'
;WITH cte As
(
SELECT *, ''Flower'' + CAST(ROW_NUMBER() OVER (PARTITION BY GardenId ORDER BY (SELECT 0)) AS VARCHAR) RN
FROM #Flowers F
)
SELECT Name,' + #ColList + N'
FROM cte
JOIN #Garden g ON g.Id = GardenId
PIVOT (MAX(Flower) FOR RN IN (' + #ColList + N')) Pvt')
DROP TABLE #Garden
DROP TABLE #Flowers
Returns
Name Flower1 Flower2
-------------------- -------------------- --------------------
myGarden rose tulip
yourGarden thistle NULL
Look at using Pivot in SQL Server. Here is a good link that goes over how it works:
http://www.kodyaz.com/articles/t-sql-pivot-tables-in-sql-server-tutorial-with-examples.aspx
Ok, i think i got it working. Try this:
with temp as
(
select 'myGarden' as name, 'test1' as flower
union
select 'myGarden','test2'
union
select 'myGarden','test5'
union
select 'abeGarden','test4'
union
select 'abeGarden','test5'
union
select 'martinGarden', 'test2'
)
select* from temp
pivot
(
max(flower)
for flower in (test1,test2,test3,test4,test5)
) PivotTable
You could also make the values in the in clause dynamic. Since this is a CTE i can't in my example.
Dynamic SQL with a cursor is the only way I can think of, and it won't be pretty.
If you only want the results for one garden at a time this would give you the data:
select gardenName from tblGarden where gardenid = 1
Union ALL
select tblFLowers.flowerName from tblFlowers where gardenid = 1

Copy Table and Merge field

Could you please help me with present SQL?
I am copy 1 table to another table and the same time merge the fields.
I get an error on the +
INSERT INTO [dSCHEMA].[TABLE_COPY_TO]
(
[FIELD_A],
[FIELD_B],
[FIELD_A] + '-' + [FIELD_B]
)
SELECT [FIELD_A]
,[FIELD_B]
FROM [dSCHEMA].[TABLE_COPY_FROM]
The appended text actually needs to be in the SELECT statement so it would look more like
Insert Into [dSCHEMA].[TABLE_COPY_TO]
(FieldA, FieldB, FieldC)
Select FieldA, FieldB, FieldA + '-' + FieldB
From [dSCHEMA].[TABLE_COPY_FROM]
I guess you are trying to create a computed column in [dSCHEMA].[TABLE_COPY_TO].
In such case, you have to define the DDL properly. Below is an example
declare #tblCopyFrom table
(
fieldA varchar(10)
,fieldB varchar(10)
)
declare #tblCopyTo table
(
fieldA varchar(10)
,fieldB varchar(10)
,fieldC AS (fieldA + '-' + fieldB) -- Computed Column
)
insert into #tblCopyFrom
select 'valA1','valB1' union all
select 'valA2','valB2' union all
select 'valA3','valB3' union all
select 'valA4','valB4' union all
select 'valA5','valB5'
insert into #tblCopyTo (fieldA,fieldB)
select * from #tblCopyFrom
select * from #tblCopyTo
Else, before insertion you can add the computed column to your table and then insert
like
Alter table TABLE_COPY_TO Add (fieldC AS (fieldA + '-' + fieldB))
insert into.......