Query for join multiple tables - sql-server

I have a database with a table 'costumers' of columns id,name. I have a separate database with custom tables names that are in format table_customer_id_1, table_customer_id_2, ...n and columns id,price,datetime (the name of each table contains the id of each row in Table 'costumers')
What is the fastest way to query the table 'costumers' and get the customer name from table costumers and the latest order date of each table_customer_id_X?
Sorry about my English are not very good and I dont know if you can understand what i m asking for! :)

Try Something like this
select
a.name,
b.DateTime,
c.datetime
from customer a
inner join tbl_customer_id1 b on b.id=a.id
inner join tbl_customer_id2 c on c.id=a.id
where a.name like '%Customer name%'
order by b.datetime , c.datetime

CREATE TABLE #Customers (id int, name varchar(10))
CREATE TABLE #Table_Customer_id_1 (id int, price decimal(18,2), datetimefield datetime)
CREATE TABLE #Table_Customer_id_2 (id int, price decimal(18,2), datetimefield datetime)
CREATE TABLE #Table_Customer_id_3 (id int, price decimal(18,2), datetimefield datetime)
INSERT INTO #Customers VALUES (1, 'Test1'), (2, 'Test2'), (3, 'Test3')
INSERT INTO #Table_Customer_id_1 VALUES
(1, 1.1, '2013-01-01'),
(2, 1.2, '2013-01-02'),
(3, 1.3, '2013-01-03'),
(4, 1.4, '2013-01-04')
INSERT INTO #Table_Customer_id_2 VALUES
(1, 2.1, '2013-02-01'),
(2, 2.2, '2013-02-02'),
(3, 2.3, '2013-02-03'),
(4, 2.4, '2013-02-04')
INSERT INTO #Table_Customer_id_3 VALUES
(1, 3.1, '2013-03-01'),
(2, 3.2, '2013-03-02'),
(3, 3.3, '2013-03-03'),
(4, 3.4, '2013-03-04')
DECLARE #SQL nvarchar(max)
;WITH CTE AS(
SELECT 'SELECT name, LastOrder FROM #Customers INNER JOIN (SELECT Max(datetimefield) AS
LastOrder, ' + CONVERT(varchar(5),id) + ' AS CustID FROM #Table_Customer_id_' +
CONVERT(varchar(5),id) + ') Tab ON #Customers.id = Tab.CustID WHERE id = ' +
CONVERT(varchar(5),id) + '' AS SqlStatement FROM #Customers
)
SELECT #SQL = STUFF((SELECT ' UNION ALL ' + SqlStatement FROM CTE FOR XML PATH('')),1,11,'')
EXEC sp_executesql #SQL
--DROP TABLE #Customers
--DROP TABLE #Table_Customer_id_1
--DROP TABLE #Table_Customer_id_2
--DROP TABLE #Table_Customer_id_3

Related

How to combine columns of two tables

I have three temporary columns,
#Pid (PartyId bigint) which contains All Partyid
#t PartyID bigint,PartyName varchar(50)SaleQty decimal(18,2)) it contains
Sale history of All parties of financial year 15-16.
#ty PartyID bigint,PartyName varchar(50)SaleQty decimal(18,2)) it contains
Sale history of All parties of financial year 16-17.
I want to combine two temporary table #t and #ty such a way that record of
any party id of both financial record should be in one row. And also if any
partyid does not have entry in anyone of the table #t and #ty then the
saleQty should be zero of in that financial year.
I have done following query to solve this.
select A.PartyName,isnull(SUM(A.SaleQty),0) as TotalSale,isnull(SUM(B.SaleQty),0) as TotalSaleB
from #t A
left join #ty B ON B.PartyId=A.PartyID
inner join #Pid P on P.PartyID=A.PartyID and B.PartyID=P.PartyID
where PartyName like'%Jain'
group by A.PartyID,A.PartyName
My Output is
PartyName TotalSale(15-16) TotalSale(16-17)
JAIN TRADERS (DHAMPUR) 16682.00 9699.00
My Desired Result should be
PartyName TotalSale(15-16) TotalSale(16-17)
JAIN TRADERS (DHAMPUR) 389.00 139.00
Sourav Traders 3899.00 0.00
Tickrej Traders 0.00 0.00
But i am unable to get the desired result. Please Help me some one here.
Try this:
declare #Pid table (PartyId bigint)
insert into #Pid values (1)
insert into #Pid values (2)
insert into #Pid values (3)
insert into #Pid values (4)
declare #t table (PartyID bigint, PartyName varchar(50), SaleQty decimal(18,2))
insert into #t values(1, 'a', 10)
insert into #t values(1, 'c', 5)
insert into #t values(2, 'b', 10)
insert into #t values(4, 'b', 20)
declare #ty table(PartyID bigint,PartyName varchar(50), SaleQty decimal(18,2))
insert into #ty values(1, 'a', 10)
insert into #ty values(2, 'c', 15)
insert into #ty values(2, 'b', 10)
select c.PartyID as PartyID, ISNULL(sum(A.SaleQty), 0) as TotalSale15_16 into #A
from #t A right join #Pid c on A.PartyID = c.PartyId
group by C.PartyID
select c.PartyID as PartyID,ISNULL(sum(B.SaleQty), 0) as TotalSale16_17 into #B
from #ty B right join #Pid c on B.PartyID = c.PartyId
group by C.PartyID
select A.PartyID, ISNULL(a.TotalSale15_16, 0) as TotalSale16_17, ISNULL(b.TotalSale16_17, 0) as TotalSale16_17
from #A a join #B b on a.PartyID = b.PartyID
drop table #A
drop table #B
result:
PartyID TotalSale16_17 TotalSale16_17
1 15.00 10.00
2 10.00 25.00
3 0.00 0.00
4 20.00 0.00
You need the #Pid to be the "base" table, and left join both tables to it.
You also need to use COALESCE (or ISNULL) to get the party name from whatever temporary table it exists in.
SELECT COALESCE(A.PartyName, B.PartyName),
COALESCE(SUM(A.SaleQty, 0)) TotalSale_t,
COALESCE(SUM(B.SaleQty, 0)) as TotalSale_ty
FROM #Pid C
LEFT JOIN #t A ON C.PartyId = A.PartyId
LEFT JOIN #ty B ON C.PartyId = B.PartyId
GROUP BY A.PartyName, B.PartyName

T- Sql aggregate query

can anyone help me figure out what I am doing wrong with this query.I am trying to filter some records from a table that contains emails sent out to clients with the status of the emails.I need to eliminate all EmailIds that has a status of Sent(1) and Bounced(0). Anything other than these two statuses are considered as Delivered(4). So the output contains only EmailId with a status of Delivered(4) for all those EmailIds that doesnt have statuses of 1 and 0.In the example below,I should see EmailId 4 too with a Status of Delivered
This is my sample set up.Really appreciate any help you guys can provide me with
create table #status
(
Id int,
Name varchar(100)
)
insert into #status (Id, Name)
values (0, 'Bounced'), (1, 'Sent'), (2, 'Clicked'),
(3, 'Opened'), (4, 'Delivered')
create table #email
(
EmailId int ,
Email varchar(100),
StatusId int
)
insert into #email (EmailId, email, StatusId)
values (1, 'rjoseph#gmail.com', 1), (1, 'rjoseph#gmail.com', 0),
(2, 'nathan#comcast.net', 1), (2, 'nathan#comcast.net', 2),
(2, 'nathan#comcast.net', 3), (3, 'nora#comcast.net', 1),
(3, 'nora#comcast.net', 2), (3, 'nora#comcast.net', 3),
(4, 'neha#comcast.net', 1)
select
e.EmailId
into
#temp
from
#email e
inner join #status st
on st.Id = e.StatusId
where
(e.StatusId not in (1,0))
group by
e.EmailId
drop table #temp
drop table #email
drop table #status
This is kind of a kludgy way to get to this (you can do this without the temporary tables, but I'm doing that here to follow your own syntax). The first query grabs the rows which match 1 AND 0. The second query returns the email IDs which do not exist in the first query:
SELECT EmailID
INTO #temp
FROM #email
WHERE StatusID = 0
AND EXISTS (SELECT 1 FROM #email WHERE StatusID = 1)
SELECT DISTINCT e.EmailID
FROM #email AS e LEFT JOIN #temp AS t
ON e.EmailID = t.EmailID
WHERE t.EmailID IS NULL
BTW: The SELECT 1 FROM ... does not have anything to do with the StatusID #1. It may seem confusing because I used SELECT 1, but it could have been SELECT 5 or SELECT 'Z'. It's mostly meaningless.
Here's the same query without the temporary table:
SELECT DISTINCT e.EmailID
FROM #email AS e
WHERE e.EmailID NOT IN (
SELECT EmailID
FROM #email
WHERE StatusID = 0
AND EXISTS (SELECT 1 FROM #email WHERE StatusID = 1)
)

Create a view in sql server using dynamic sql inside

I know this sounds weird, but is it possible to have a view that use dynamic SQL to build it? I know the views are compiled so most probably this is not possible. For sure I could do it using an stored procedure instead but I just want to make sure is not possible.
Here I have an example:
declare #Table1 as table (
Id int,
Name nvarchar(50),
Provider nvarchar(50)
)
insert #Table1 values (1, 'John', 'Provider1')
insert #Table1 values (2, 'Peter', 'Provider1')
insert #Table1 values (3, 'Marcus', 'Provider2')
declare #Table2 as table (
Id int,
Info nvarchar(50),
AnotherInfo nvarchar(50)
)
insert #Table2 values (1, 'Expense', '480140')
insert #Table2 values (1, 'Maintenance', '480130')
insert #Table2 values (2, 'Set Up Cost', '480150')
insert #Table2 values (2, 'Something', '480160')
--No columns from Table2
select a.Id, a.Name, a.Provider from #Table1 a left join #Table2 b on a.Id = b.Id
--With columns from Table2
select a.Id, a.Name, a.Provider, b.Info, b.AnotherInfo from #Table1 a left join #Table2 b on a.Id = b.Id
The first select looks like I have repeated data, which is normal because I did the left join, the problem is that for avoiding that I need to perform a distinct and this is what I don't want to do. My example is short but I have much more columns and table is quite big.

How do I find records out of order - SQL?

Let's say I have a table with an ID Identity column, some data, and a datestamp. Like this:
1 data 5/1/2013 12:30
2 data 5/2/2013 15:32
3 data 5/2/2013 16:45
4 data 5/3/2013 9:32
5 data 5/5/2013 8:21
6 data 5/4/2013 9:36
7 data 5/6/2013 11:42
How do I write a query that will show me the one record that is timestamped 5/4? The table has millions of records. I've done some searching, but I don't know what to call what I'm searching for. :/
declare #t table(id int, bla char(4), timestamp datetime)
insert #t values
(1,'data','5/1/2013 12:30'),
(2,'data','5/2/2013 15:32'),
(3,'data','5/2/2013 16:45'),
(4,'data','5/3/2013 9:32'),
(5,'data','5/5/2013 8:21'),
(6,'data','5/4/2013 9:36'),
(7,'data','5/6/2013 11:42')
select timestamp
from
(
select rn1 = row_number() over (order by id),
rn2 = row_number() over (order by timestamp), timestamp
from #t
) a
where rn1 not in (rn2, rn2-1)
in 2008 r2, this would be a way
DECLARE #Table AS TABLE
(id INT , ladate DATETIME)
INSERT INTO #Table VALUES (1, '2013-05-01')
INSERT INTO #Table VALUES (2, '2013-05-02')
INSERT INTO #Table VALUES (3, '2013-05-03')
INSERT INTO #Table VALUES (4, '2013-05-05')
INSERT INTO #Table VALUES (5, '2013-05-04')
INSERT INTO #Table VALUES (6, '2013-05-06')
INSERT INTO #Table VALUES (7, '2013-05-07')
INSERT INTO #Table VALUES (8, '2013-05-08')
--I added the records in the sort order but if not just make sure you are sorted in the query
SELECT t2.ladate FROM #Table T1
INNER JOIN #Table T2 ON T1.Id = T2.Id + 1
INNER JOIN #Table t3 ON t2.id = t3.id + 1
WHERE t3.ladate < t2.ladate AND t2.ladate > t1.ladate
-- I made the assumption that your Id are all there, 1,2,3,4,5.... none missing... if there are rownumbers missing, you can use row_number()

T-SQL SELECT query to return combined result of multiple tables

I am wondering if it is possible and more efficient to do something that I am presently doing in code, to do in T-SQL instead.
I have a database with courses. Each course can have different offerings which are variations of the course at different locations and at different awards.
Here's my (simplified) database structure and some sample data:
CREATE TABLE tblCourse (CourseId int, CourseName varchar(50))
CREATE TABLE tblOffering (OfferingId int, CourseId int, LocationId int, AwardId int)
CREATE TABLE tblLocation (LocationId int, LocationName varchar(50))
CREATE TABLE tblAward (AwardId int, AwardName varchar(50))
INSERT INTO tblCourse VALUES (1, 'Course A')
INSERT INTO tblCourse VALUES (2, 'Course B')
INSERT INTO tblOffering VALUES (1, 1, 1, 1)
INSERT INTO tblOffering VALUES (2, 1, 2, 1)
INSERT INTO tblOffering VALUES (3, 1, 3, 1)
INSERT INTO tblOffering VALUES (4, 1, 1, 2)
INSERT INTO tblOffering VALUES (5, 2, 3, 1)
INSERT INTO tblLocation VALUES (1, 'Location A')
INSERT INTO tblLocation VALUES (2, 'Location B')
INSERT INTO tblLocation VALUES (3, 'Location C')
INSERT INTO tblAward VALUES (1, 'Award A')
INSERT INTO tblAward VALUES (2, 'Award B')
What I want to retrieve from SQL is a single row for each course/award combination. Each row would have columns for each location and whether a course of that CourseId/AwardId combination was available. There would be now rows for course/award combinations that have no offerings.
The required result, from the sample data, would be a recordset like this:
CourseId | CourseName | AwardId | AwardName | LocationA | LocationB | LocationC
---------+------------+---------+-----------+-----------+-----------+----------
1 | Course A | 1 | Award A | True | True | True
1 | Course A | 2 | Award B | True | NULL | NULL
2 | Course B | 1 | Award A | NULL | NULL | True
(NULL could also be False)
At present I am doing a simple SELECT statement with various JOINS which gives me multiple rows for each course/award combination, then I loop through all rows in my code and build the required result. However, I don't think this is so efficient as I also need to page results.
I think I could do this fairly easily in a stored procedure by creating a temporary table and a bunch of separate queries, but I don't think that would be too efficient. Wondering if there is a better way of doing it in T-SQL???
So to clarify, what I am looking for is a T-SQL query or stored procedure that will produce the above sample recordset, and which I could adapt paging to.
NB. I am using SQL Server 2008
For Dynamic columns:
DECLARE #COLUMNS VARCHAR(max)
,#query varchar(1024)
,#True varchar(6)
SELECT #COLUMNS =
COALESCE(
#Columns + ',[' + L.LocationName + ']',
'[' + L.LocationName +']'
)
FROM tblLocation L
SELECT #True = '''True'''
SELECT #QUERY = 'SELECT C.CourseName
,A.AwardName
, pvt.*
FROM (SELECT O.OfferingID AS OID
,O.AwardID AS AID
,O.CourseID AS CID
,L.LocationName AS LID
FROM tblOffering O Inner Join tblLocation L on L.LocationID = O.LocationID) AS S
PIVOT
(
count(oID) For LID IN (' +#COLUMNS+ ')
) As pvt
inner join tblCourse C on C.CourseID = CID
inner join tblAward A on A.AwardID = pvt.AID'
EXEC (#QUERY)
GO
This will produce a paginated version of your example results:
declare #tblCourse as table (CourseId int, CourseName varchar(50))
declare #tblOffering as table (OfferingId int, CourseId int, LocationId int, AwardId int)
declare #tblLocation as table (LocationId int, LocationName varchar(50))
declare #tblAward as table (AwardId int, AwardName varchar(50))
INSERT INTO #tblCourse VALUES (1, 'Course A')
INSERT INTO #tblCourse VALUES (2, 'Course B')
INSERT INTO #tblOffering VALUES (1, 1, 1, 1)
INSERT INTO #tblOffering VALUES (2, 1, 2, 1)
INSERT INTO #tblOffering VALUES (3, 1, 3, 1)
INSERT INTO #tblOffering VALUES (4, 1, 1, 2)
INSERT INTO #tblOffering VALUES (5, 2, 3, 1)
INSERT INTO #tblLocation VALUES (1, 'Location A')
INSERT INTO #tblLocation VALUES (2, 'Location B')
INSERT INTO #tblLocation VALUES (3, 'Location C')
INSERT INTO #tblAward VALUES (1, 'Award A')
INSERT INTO #tblAward VALUES (2, 'Award B') -- This had id 1 in your example.
-- Set the following parameters to control paging:
declare #PageSize as Int = 5
declare #PageNumber as Int = 1
; with CourseAwardSummary as (
select distinct C.CourseId, C.CourseName, A.AwardId, A.AwardName,
case when exists ( select 42 from #tblOffering where CourseId = C.CourseId and AwardId = A.AwardId and LocationId = 1 ) then 'True' end as LocationA,
case when exists ( select 42 from #tblOffering where CourseId = C.CourseId and AwardId = A.AwardId and LocationId = 2 ) then 'True' end as LocationB,
case when exists ( select 42 from #tblOffering where CourseId = C.CourseId and AwardId = A.AwardId and LocationId = 3 ) then 'True' end as LocationC
from #tblCourse as C inner join
#tblOffering as O on O.CourseId = C.CourseId inner join
#tblAward as A on A.AwardId = O.AwardId
),
CourseAwardSummaryRows as (
select *, Row_Number() over ( order by CourseName, AwardName ) as RowNumber
from CourseAwardSummary
)
select CourseId, CourseName, AwardId, AwardName, LocationA, LocationB, LocationC
from CourseAwardSummaryRows
where ( #PageNumber - 1 ) * #PageSize + 1 <= RowNumber and RowNumber <= #PageNumber * #PageSize
order by CourseName, AwardName
The following query does this by joining and aggregating the offering table, and then joining the result to the course and award tables:
select c.CourseId, c.CourseName, oa.AwardId, oa.AwardName,
oa.LocationA, oa.LocationB, oa.LocationC
from tblCourse c left outer join
(select o.CourseId, o.AwardId, a.awardName
max(case when LocationName = 'Location A' then 'true' end) as LocationA,
max(case when LocationName = 'Location B' then 'true' end) as LocationB,
max(case when LocationName = 'Location C' then 'true' end) as LocationC
from tblOffering o join
tblLocation l
on o.LocationId = l.LocationId join
tblAward a
on a.awardID = o.AwardId
group by o.CourseId, o.AwardId, a.awardName
) oa
on oa.CourseId = c.CourseId

Resources