I need to show in a temporary table one user a many phone of that user, but I'm stuck
in the select, I need something like this:
user1 phone1 phone2 phone3 phone4 phone5
11816116-5 8555588 77877888 33254477 224474 45777885
this is the code that I'm trying:
select
phone As phonenum
Into #Tmp_phonenumber
From
clients_has_phones
where
user_number='11816116-5'
thanks in advance.
I can not think of a good way of doing the select statement other than by self joining on how ever many phone numbers your user may have.. With that being said you can try this for your select statement:
;With CTE_Main as (
Select
id
,Fono
,row_number()
Over(Partition by ID order by Fono) as RN
From sucursales
), CTE_Users as (
Select
id as id_num
from sucursales
group by id
)
Select
id_num
,a.Fono as Phone_1
,b.Fono as Phone_2
,c.Fono as Phone_3
,d.Fono as Phone_4
,e.Fono as Phone_5
From CTE_Users as realz
Left Join [CTE_Main] as a on a.id = realz.id_num and a.RN = 1
Left Join [CTE_Main] as b on b.id = realz.id_num and b.RN = 2
Left Join [CTE_Main] as c on c.id = realz.id_num and c.RN = 3
Left Join [CTE_Main] as d on d.id = realz.id_num and d.RN = 4
Left Join [CTE_Main] as e on e.id = realz.id_num and e.RN = 5
I know its kind of lengthy but it will display the results in the way that you want them.. My example only uses 5 rows but it should be pretty self explanatory.
Sql Fiddle: http://sqlfiddle.com/#!3/496f6/1
Related
I have the following tables:
Customers
ID Name
============
1 John
2 Alice
3 Bob
Orders
ID CustomerID Status
==========================
1001 1 1
1002 2 1
1003 2 2
1004 3 2
I'd like to join tables showing one entry per customer only (the one with lowest Status) i.e.
ID Name OrderID
======================
1 John 1001
2 Alice 1002
3 Bob 1004
Thanks to the answer to this question, I chose 2 solutions which produce the same output:
Solution 1
SELECT c.id, c.name, o.id FROM customers AS c
INNER JOIN orders AS o ON
c.id = o.customerid
WHERE o.status = (SELECT MIN(status) FROM orders WHERE customerid = c.id)
Solution 2
SELECT c.id, c.name, o.id FROM customers as c
INNER JOIN orders AS o ON
o.id = (SELECT TOP 1 id FROM orders WHERE customerid = c.id ORDER BY status)
Trying to understand which one runs faster, I used SQL Fiddle View Execution Plan which gave the following:
Solution 1
Solution 2
How to interpret those diagrams and which one performs faster?
Using MS SQL Server 2016.
Here's my breakdown and the last one is my suggestion to you.
Query Cost 67%
SELECT c.id, c.name, o.id FROM #Customers AS c
INNER JOIN #Orders AS o ON
c.id = o.customerid
WHERE o.status = (SELECT MIN(status) FROM #Orders WHERE customerid = c.id)
Query Cost 66%
SELECT c.id, c.name, o.id FROM #Customers as c
INNER JOIN #Orders AS o ON
o.id = (SELECT TOP 1 id FROM #Orders WHERE customerid = c.id ORDER BY status)
Query Cost 47%
SELECT
x.CustID,
x.Name,
x.OrderID
FROM (SELECT
C.id CustID,
c.Name,
o.ID OrderID,
o.status,
ROW_NUMBER() OVER (PARTITION BY c.id ORDER BY o.status) rn
FROM #Customers c
INNER JOIN #Orders o
ON o.CustomerID = c.ID) x
WHERE x.rn = 1
I'm trying to display the data so that only one line is displayed per customer, i'm having trouble with trying to achieve that with my code as its returning all records, can anyone help
SELECT customerOrdrs.NAME AS 'Name',
customerOrdrs.currentbalance -
Sum(COALESCE(customerOrdrs.revisedbalance, 0)) AS 'RevisedBalance',
sold AS 'NumberOfItemsSold'
FROM customers,
(SELECT c.NAME AS NAME,
c.balance AS CurrentBalance,
i.qty AS RevisedBalance,
( Min(s.price) * i.qty ) AS Sold
FROM customers c
INNER JOIN sales o
ON c.NAME = o.custname
INNER JOIN purchases i
ON i.orderno = o.orderno
INNER JOIN contracters s
ON i.item = s.item
GROUP BY c.NAME,
c.balance,
i.qty) customerOrdrs
GROUP BY customerOrdrs.NAME,
customerOrdrs.currentbalance,
sold
I'm not sure how your data looks but I have reformatted the query and there are a few things I've noticed off the bat.
I have removed the subquery as I don't believe it is necessary - in addition your original query is referring to customer table twice without defining a join
Select [C].[Name] As [Name]
, [CurrentBalance] = [C].[Balance]
, [RevisedBalance] = [C].[Balance] - Sum([P].[Qty])
, [Sold] = ( Min([CO].[Price]) * sum([P].[Qty]) )
From [CUSTOMERS] [C]
Inner Join [Sales] [s]
On [C].[Name] = [s].[custName]
Inner Join [Purchases] [P]
On [P].[OrderNo] = [s].[OrderNo]
Inner Join [Contracters] [CO]
On [P].[Item] = [CO].[Item]
Group By [C].[Name]
, [C].[Balance];
Lets say that i have a 3 tables:
Cars
Id
CarColorHistory
Id
CarID
ColorID
ModificationDate
Color:
Id
ColorName
I want to select all cars and their colors but the important thing is, that color for the car is the last modified color from CarColorHistory table.
I need to use join to do this.
Example:
Cars:
1
2
CarColorhistory:
1 1 1 26/03/2012 -> (actual color, can be take by date or id)
2 1 2 25/03/2012
3 2 2 25/03/2012
Color:
1 Blue
2 Red
I need to get result: (car id, colorName)
1 Blue
2 Red
I tried make it by joining Cars table and CarColorHistory table but I get cars for all colors. I need only actual color (last added).
Please help
Try this:
select c.id, colorname
from cars c
inner join CarColorHistory h on c.id = h.CarID
inner join Color c2 on h.colorid = c2.id
where h.ModificationDate = (select max(ModificationDate)
from CarColorHistory x where c.id = x.CarId)
There are several ways that you can get the result. You can use a subquery to get the max(modificationdate):
select c.id, r.colorname
from cars c
inner join CarColorhistory h1
on c.id = h1.carid
inner join
(
select max(modificationdate) MaxDate,
carid
from CarColorhistory
group by carid
) h2
on h1.carid = h2.carid
and h1.modificationdate = h2.maxdate
inner join color r
on h1.colorid = r.id
See SQL Fiddle with Demo
Or since you are using SQL Server you can use ranking functions:
select id, colorname
from
(
select c.id, r.colorname,
row_number() over(partition by c.id order by modificationdate desc) rn
from cars c
inner join CarColorhistory h1
on c.id = h1.carid
inner join color r
on h1.colorid = r.id
) src
where rn = 1;
See SQL Fiddle with Demo
This should do the trick for you:
SELECT c.id, (
SELECT co.ColorName FROM Color co
WHERE co.id = (
SELECT TOP 1 ColorID FROM CarColorHistory
WHERE CarID = c.id
ORDER BY ModificationDate DESC
)
) AS ColorName
One way to do this might be with just using a subquery, like posted before, since you are using t-sql you should also be able to do it with an apply:
SELECT
Cars.Id, LatestColors.ColorID, LatestColors.ModificationDate
FROM Cars
CROSS APPLY (
SELECT TOP 1
ColorID, ModificationDate
FROM CarColorHistory
WHERE CarID = Cars.ID
ORDER BY ModificationDate DESC
) AS LatestColors
You can try this if you have Sql Server 2005 or greater:
You can try here, how Common table expression is working: Sql Fiddle demo
;WITH CTE_Cars(CarID, MaxDate)
AS
(
SELECT CarID, MAX(ModificataionDate) AS MaxDate
FROM CarColorHistory
GROUP BY CarID
)
SELECT CTE_Cars.CarID, Color.ColorName
FROM
CTE_Cars
INNER JOIN CarColorHistory ON CarColorHistory.CarID = CTE_Cars.CarID AND
CarColorHistory.ModificataionDate = CTE_Cars.MaxDate
INNER JOIN Color ON Color.id = CarColorHistory.ColorId
I'm not sure if this is the best way, but this is the way I do it. First get the values you want out of the tables using the MAX and then use that result as a table to JOIN in order to eliminate unwanted values.
SELECT c.ID, Color.Color
From Cars c JOIN CarColorHistory h on c.id = h.CarID
JOIN Color on h.ColorID = Color.ID
JOIN
--Create a table with only the latest value and the car ID
(
SELECT c.ID, Max(h.TimeStamp) as time
FROM Cars c JOIN CarColorHistory h on c.id = h.CarID
JOIN Color on h.ColorID = Color.ID
Group by c.ID --Join the table on latest time to get rid of old timestamps
) Max on Max.ID = c.ID and h.TimeStamp=max.time
I'm trying to modify an existing query that is displaying duplicate rows sharing an ID, while having different secondary ID's.
SELECT IM.*, C.Client, U.Name, R.FrequencyUnit, R.FrequencyDuration, R.RIID
FROM itemsMisc IM
LEFT JOIN Clients C on C.ClientID = IM.ClientID
LEFT JOIN Users U on U.UserID = IM.UserID
LEFT JOIN Recurringitem R ON (R.ClientID = C.ClientID AND IM.Rate = R.Rate AND IM.Title = R.Title)
WHERE (IM.CID = <cfqueryparam cfsqltype="CF_SQL_INTEGER" value="#CID#">)
AND (IM.Invoiced = 0)
ORDER BY IM.DateCompleted ASC;
What's happening is if the same user makes 2 similar recurring items, a duplicate rows show up with the same IMID(from itemsMisc) but with different RIID's from Recurringitems.
I tried GROUP BY on IMID, found I had to include all of the select items in the GROUP BY, which got me no where.
SELECT IM.IMID, IM.UserID, IM.ClientID, IM.Rate, IM.Title, IM.CID, IM.QTY, IM.DateCompleted, C.Client, U.Name, R.FrequencyUnit, R.FrequencyDuration, R.RBID
FROM ItemMisc IM
LEFT JOIN Clients C on C.ClientID = IM.ClientID
LEFT JOIN Users U on U.UserID = IM.UserID
LEFT JOIN Recurringitem R ON (R.ClientID = C.ClientID AND IM.Rate = R.Rate AND IM.Title = R.Title)
WHERE (IM.CID = <cfqueryparam cfsqltype="CF_SQL_INTEGER" value="#CID#">)
AND (IM.Invoiced = 0)
GROUP BY IM.IMID, IM.UserID, IM.ClientID, IM.Rate, IM.Title, IM.CID, IM.QTY, IM.DateCompleted, C.Client, U.Name, R.FrequencyUnit, R.FrequencyDuration, R.RBID
ORDER BY IM.DateCompleted ASC;
Please let me know if I can clarify anything.
Thanks in advance
You have some options
You can drop R.RBID from your select and group by clauses
Create a unique key on Rate, Title, FrequencyUnit, FrequencyDuration so you don't get "similar items
Only grab one R.RBID per Rate, Title, FrequencyUnit, FrequencyDuration
If its the last one you want you can use row_number to grab one and only one RBID per (rate,title, frequencyunit and frequencyduration)
WITH cte
AS (SELECT IM.imid, IM.userid, IM.clientid, IM.rate,
IM.title, IM.cid, IM.qty, IM.datecompleted,
C.client, U.name, R.frequencyunit, R.frequencyduration,
R.rbid,
Row_number()
OVER (
partition BY R.rate, R.title, R.frequencyunit, R.frequencyduration
ORDER BY R.rbid ) rn
FROM itemmisc IM
LEFT JOIN clients C
ON C.clientid = IM.clientid
LEFT JOIN users U
ON U.userid = IM.userid
LEFT JOIN recurringitem R
ON ( R.clientid = C.clientid
AND IM.rate = R.rate
AND IM.title = R.title )
WHERE (IM.CID = <cfqueryparam cfsqltype="CF_SQL_INTEGER" value="#CID#">)
AND (IM.Invoiced = 0)
GROUP BY IM.imid, IM.userid, IM.clientid, IM.rate,
IM.title, IM.cid, IM.qty, IM.datecompleted,
C.client, U.name, R.frequencyunit, R.frequencyduration,
R.rbid)
SELECT *
FROM cte
WHERE rn = 1
ORDER BY im.datecompleted ASC
Note: You may define "similar items" by modifying the members of the partition BY
I have Table Users
I also have Table Departments
And I have a map table between Users and Departments.
I want to find all users name and Id which appears in all departments.
for example if there's 5 departments and Paul is only in department #1 , so Paul will not be in the output list.
He would , only if he is listed in all departments (1..5)
I started doing something which is very long (readly long) using temp table and I assume there is a better way.
I also create a Sql Fiddle.
There's more than one way of doing this.
You could require that the number of departments that the user is in equals the total number of departments:
SELECT
*
FROM
Users
INNER JOIN
(
SELECT userId, COUNT(*) c FROM MapUserstoDepartments
GROUP BY userId
HAVING COUNT(*) = (SELECT COUNT(*) FROM Departments)
) UsersInAllDepartments
ON Users.userId = UsersInAllDepartments.userId
You could require that removing the user's departments from the list of all departments leaves nothing:
SELECT *
FROM Users
WHERE NOT EXISTS
(
SELECT depId FROM Departments
EXCEPT
SELECT depId FROM MapUserstoDepartments WHERE userId = Users.userId
)
I'm sure there are others.
Try this
SELECT u.userId, u.UserName
FROM MapUserstoDepartments m INNER JOIN
Users u ON u.userId = m.userId
GROUP BY u.userId, u.UserName
HAVING COUNT(m.depId) = (SELECT COUNT(*) FROM Departments)
That will produce
| USERID | USERNAME |
---------------------
| 100 | John |
And sqlfiddle
You can do it like this:
select u.*
from Users u
where not exists
(
select 1
from Departments d
where not exists
(
select 1
from MapUserstoDepartments m
where d.depId = m.depId
and m.userId = u.userId
)
)
SQL Fiddle
Is this what you want?
Select Tbl.userID , Tbl.username from (Select u.userid , u.username ,
count(u.userid) as Count from MapUsersToDepartments m
inner join Users u on m.UserID = u.userID
group by u.userid , u.username)Tbl
where Tbl.Count = (Select count(*) from Departments)
Here is the fiddle
http://sqlfiddle.com/#!3/5a960/53
select
Users.userId,
count(Departments.depId),
count(MapUserstoDepartments.userId)
from
Users
left join MapUserstoDepartments on MapUserstoDepartments.userId = Users.userId
left join Departments on Departments.depId = MapUserstoDepartments.depId
group by
Users.userId
having
(SELECT COUNT(*) from Departments) = count(MapUserstoDepartments.userId)
Try below query. Let me know if this will help
select * from users where userid in
(select userid from MapUserstoDepartments
group by userid
having count(userid) = 5)