I have an SQL query like
select name from customers where id in (1,2,3,4,5)
this will return me 5 rows.
What I am trying is
select Q1,Q2,Q3,Q4,Q5 from(select name from customers where id in (1,2,3,4,5)
)d pivot( max(name) for names in (Q1,Q2,Q3,Q4,Q5)
) piv;
to convert these 5 rows into 5 columns.
But I am getting null values in columns.
I don't know where am I doing wrong.
Any kind of help , suggestion would be appreciated.
Thanks
You can try in this way, you are pivoting the name and selecting the name under value also so please first make is sure if there is a value for that ids and retrieve the value for which you are trying pivoting:
create table #customers(id int, name varchar(50), fee int)
insert into #customers values
(1, 'Q1', 100),
(2, 'Q2', 200),
(3, 'Q3', 300),
(4, 'Q4', 400),
(5, 'Q5', 500),
(6, 'Q5', 600),
(7, 'Q5', 700)
select Q1,Q2,Q3,Q4,Q5
from(select name, fee from #customers where id in (1,2,3,4,5)
)d pivot(SUM(fee) for name in (Q1,Q2,Q3,Q4,Q5)
) piv;
OUTPUT:
Q1 Q2 Q3 Q4 Q5
100 200 300 400 500
What respective value you want to display under name, if you mention that then we can provide more exact solution for that. Hope you can change your code accordingly.
Related
It is necessary to build a summary table based on data about the customer and their payments, where the columns will be the sequential number of the contract (contact_number) and the year (year) grouped by gender. The main condition is that contact_number and year should be dynamically generated.
Test data:
CREATE TABLE loans
(
loan_id int,
client_id int,
loan_date date
);
CREATE TABLE clients
(
client_id int,
client_name varchar(20),
gender varchar(20)
);
INSERT INTO CLIENTS
VALUES (1, arnold, 'male'),
(2, lilly, 'female'),
(3, betty, 'female'),
(4, tom, 'male'),
(5, jim, 'male');
INSERT INTO loans
VALUES (1, 1, '20220522'),
(2, 2, '20220522'),
(3, 3, '20220525'),
(4, 4, '20220525'),
(5, 1, '20220527'),
(6, 2, '20220527'),
(7, 3, '20220601'),
(8, 1, '20220603'),
(9, 2, '20220603'),
(10, 1, '20220603');
Formation of columns can be done using the case when construct, but this option is not suitable due to the need to constantly add new lines in the query when adding data.
My code:
with cte as
(
select
l.client_id,
loan_date,
extract(year from loan_date) as year,
client_name,
gender,
row_number() over (partition by l.client_id order by loan_date asc) as serial_number_contact
from
loans l
inner join
client c on l.client_id = c.client_id
)
select
gender
, year
, contract_number
, count(*)
from cte
group by gender, year, contract_number
order by year, contract_number
expected Output :
sex
1 contract, 2022
2 contract, 2022
3 contract, 2022
male
2
2
1
female
4
1
1
RDMBS - postgres
I have a table where I'm trying to count the distinct number of members per group. I know there's duplicates based on the count(distinct *) function. But when I try to group them into the group and count distinct, it's not spitting out the number I'd expect.
select count(distinct memberid), count(*)
from dbo.condition c
output:
count
count
303,781
348,722
select groupid, count(*), count(distinct memberid)
from dbo.condition c
group by groupid
output:
groupid
count
count
2
19,984
19,984
3
25,689
25,689
5
14,400
14,400
24
56,058
56,058
25
200,106
200,106
29
27,847
27,847
30
1,370
1,370
31
3,268
3,268
The numbers in the second query equate when they shouldn't be. Does anyone know what I'm doing wrong? I need the 3rd column to be equal to 303,781 not 348,722.
Thanks!
There's nothing wrong with your second query. Since you're aggregating on the "groupid" field, the output you get tells you that there are no duplicates within the same groupid of the "memberid" values (basically counting values equates to counting distinctively).
On the other hand, in the first query the aggregation happens without any partitioning, whose output hints there are duplicate values across different "groupid" values.
Took the liberty of adding of an example that corroborates your answer:
create table aa (groupid int not null, memberid int not null );
insert into aa (groupid, memberid)
values
(1, 1), (1, 2), (1, 3), (2, 1), (3, 1), (3, 2), (3, 3), (4, 1), (4, 2), (4, 3), (4, 5), (5, 3)
select groupid, count(*), count(distinct memberid)
from aa group by groupid;
select count(*), count(distinct memberid)
from aa
I want to do running total but there is no unique column or id column to be used in over clause.
CREATE TABLE piv2([name] varchar(5), [no] int);
INSERT INTO piv2
([name], [no])
VALUES
('a', 1),
('a', 2),
('a', 3),
('a', 4),
('b', 1),
('b', 2),
('b', 3);
there are only 2 columns, name which has duplicate values and the no on which I want to do running total in SQL Server 2017 .
expected result:
a 1
a 3
a 6
a 10
b 11
b 13
b 16
Any help?
The following query would generate the output you expect, at least for the exact sample data you did show us:
SELECT
name,
SUM(no) OVER (ORDER BY name, no) AS no_sum
FROM piv2;
If the order you intend to use for the rolling sum is something other than the order given by the name and no columns, then you should reveal that logic along with sample data.
T-SQL question: I have a breakdown of the visits by year of a person. I want to get a count of the total visits per year and then create a column for each year to summarize the total. The way I have it now it only returns the totals per year for the columns on separate rows. How can I combine them?
Example temp table and code...
CREATE TABLE #Events
(
Col1 int PRIMARY KEY,
Person Varchar(20),
VisitYear INT,
VisitInfo Varchar(20)
)
INSERT INTO #Events
VALUES (1, 'User1', '2017', 'Combo'), (2, 'User1', '2017', 'Special'),
(3, 'User1', '2018', 'ComboBig'), (4, 'User2', '2017', 'Special'),
(5, 'User2', '2017', 'ComboBig'), (6, 'User2', '2018', 'ComboBig'),
(7, 'User2', '2018', 'Special'), (8, 'User2', '2018', 'Special2'),
(9, 'User3', '2018', 'Combo')
SELECT DISTINCT
Person,
VisitYear,
VisitInfo,
COUNT(Person) OVER(PARTITION BY Person, VisitYear) AS TtlPerYear
INTO
#EventCountPerYear
FROM
#Events E
SELECT *
FROM #EventCountPerYear
SELECT DISTINCT
E1.Person,
CASE WHEN E1.VisitYear IN ('2017') THEN E1.TtlPerYear END AS '2017_Visits',
CASE WHEN E1.VisitYear IN ('2018') THEN E1.TtlPerYear END AS '2018_Visits'
FROM
#EventCountPerYear E1
Right now the results comes split with the Year counts on separate rows. Is there a way to have it result in just one clean row of data?
Images of current and desired results listed below...
The current results:
Desired results]
On SQL-Server you could use a PIVOT:
SELECT Person, [2017], [2018]
FROM (SELECT Person, VisitYear FROM #Events) src
PIVOT (COUNT(VisitYear) FOR VisitYear IN ([2017],[2018])) pvt
GO
Person | 2017 | 2018
:----- | ---: | ---:
User1 | 2 | 1
User2 | 2 | 3
User3 | 0 | 1
dbfiddle here
You are on the path to using conditional aggregation. This looks like:
SELECT E1.Person
SUM(CASE WHEN E1.VisitYear IN (2017) THEN E1.TtlPerYear END) AS [2017_Visits],
SUM(CASE WHEN E1.VisitYear IN (2018) THEN E1.TtlPerYear END) AS [2018_Visits]
FROM #EventCountPerYear E1
GROUP BY E1.Person;
Notes:
Don't put single quotes around numeric values, such as the year.
Don't use single quotes for column aliases. In fact, only use single quotes for string and date constants.
This adds the GROUP BY clause.
How do I sort the results into the following example by the sellers name while keeping the rollup at the bottom?
Since the the grouping is applied to the nested SELECT I can't use ORDER BY and since the grouping isn't applied at the top level I can't use the GROUPING either.
Click here to see the working example in SQL Fiddle.
CREATE TABLE Sales
(
SellerID INT
, StoreID INT
, Price MONEY
);
CREATE TABLE Sellers
(
SellerID INT
, Name VARCHAR(50)
)
INSERT INTO Sales VALUES
(1, 1, 100),
(1, 1, 100),
(1, 1, 100),
(2, 2, 200),
(2, 2, 200),
(3, 2, 250),
(3, 2, 250),
(3, 2, 250),
(3, 2, 250);
INSERT INTO Sellers VALUES
(1, 'C. Thirdplace'),
(2, 'A. Firstplace'),
(3, 'B. Secondplace');
SELECT s.Name AS Seller_Name
, x.TotalSales AS Total_Sales
FROM
(
SELECT s.SellerID AS SellerID
, SUM(s.Price) AS TotalSales
FROM Sales s
GROUP BY s.SellerID
WITH ROLLUP
) x
LEFT JOIN Sellers s
ON s.SellerID = x.SellerID;
Which produces the following result:
SELLER_NAME TOTAL_SALES
--------------- -----------
C. Thirdplace 300
A. Firstplace 400
B. Secondplace 1000
(null) 1700
ORDER BY
CASE WHEN seller_name IS NULL THEN 1 ELSE 0 END,
seller_name