Pivot / Unpivot the following data - sql-server

I'm new to Pivots so I'm not exactly sure how I would need to do this.
I have the following data:
I need to pivot/unpivot the above data.
I need the following Columns:
GLLink
AccType
Budget
Budget Value
I've tried developing the code, but I'm afraid I am doing it completely wrong:
select
*
from
(
select
*
from Budgets
) x
unpivot
(
GLLink for Budget in ([AccType])
) p
order by GLLink, Budget
The results I would require should look like this:

Assuming the data you showed us are in a table named 'yourtable', here is the cross apply way:
select t.GLLink,t.Acctype,u.*
from yourtable t
cross apply
(
values
('Budget01',Budget01),
('Budget02',Budget02),
('Budget03',Budget03),
('Budget04',Budget04),
('Budget05',Budget05),
('Budget06',Budget06),
('Budget07',Budget07)
)u(Budget,[Budget Value])
The way it works: cross apply "sees" one row each time. For this row, it uses the values() operator to create a table, so we make the pairs as you need them. In the end, we give a name to this table (u for unpivoted), and also name the columns.
Converting columns to rows is unpivoting (what you need), pivoting is the reverse.

Related

how to select first rows distinct by a column name in a sub-query in sql-server?

Actually I am building a Skype like tool wherein I have to show last 10 distinct users who have logged in my web application.
I have maintained a table in sql-server where there is one field called last_active_time. So, my requirement is to sort the table by last_active_time and show all the columns of last 10 distinct users.
There is another field called WWID which uniquely identifies a user.
I am able to find the distinct WWID but not able to select the all the columns of those rows.
I am using below query for finding the distinct wwid :
select distinct(wwid) from(select top 100 * from dbo.rvpvisitors where last_active_time!='' order by last_active_time DESC) as newView;
But how do I find those distinct rows. I want to show how much time they are away fromm web apps using the diff between curr time and last active time.
I am new to sql, may be the question is naive, but struggling to get it right.
If you are using proper data types for your columns you won't need a subquery to get that result, the following query should do the trick
SELECT TOP 10
[wwid]
,MAX([last_active_time]) AS [last_active_time]
FROM [dbo].[rvpvisitors]
WHERE
[last_active_time] != ''
GROUP BY
[wwid]
ORDER BY
[last_active_time] DESC
If the column [last_active_time] is of type varchar/nvarchar (which probably is the case since you check for empty strings in the WHERE statement) you might need to use CAST or CONVERT to treat it as an actual date, and be able to use function like MIN/MAX on it.
In general I would suggest you to use proper data types for your column, if you have dates or timestamps data use the "date" or "datetime2" data types
Edit:
The query aggregates the data based on the column [wwid], and for each returns the maximum [last_active_time].
The result is then sorted and filtered.
In order to add more columns "as-is" (without aggregating them) just add them in the SELECT and GROUP BY sections.
If you need more aggregated columns add them in the SELECT with the appropriate aggregation function (MIN/MAX/SUM/etc)
I suggest you have a look at GROUP BY on W3
To know more about the "execution order" of the instruction you can have a look here
You can solve problem like this by rank ordering the results by a key and finding the last x of those items, this removes duplicates while preserving the key order.
;
WITH RankOrdered AS
(
SELECT
*,
wwidRank = ROW_NUMBER() OVER (PARTITION BY wwid ORDER BY last_active_time DESC )
FROM
dbo.rvpvisitors
where
last_active_time!=''
)
SELECT TOP(10) * FROM RankOrdered WHERE wwidRank = 1
If my understanding is right, below query will give the desired output.
You can have conditions according to your need.
select top 10 distinct wwid from dbo.rvpvisitors order by last_active_time desc

Determine if columns have duplicate values sql

I am trying to figure out a way to check if their is repeated values in rows that are shared.
Example:
HMOID Name Addon10 Addon15 Addon20
RFFF Blah img path1 img path2 img path1
For my example, I would like to check if any of the addons for RFFF have any repeated value. In my example above, 'RFFF' has two images that are the same in Addon10 and Addon20 (The images have a path. so currently, they look like
http://oc2-reatest.regalmed.local/ocupgrade52/images/NDL_SCAN_SR.PNG).
I would like to be able to do this for multiple rows. I thought the following would give me an idea how to begin:
select * from HlthPlan
Group By HMO1A, HMONM
Having COUNT(*) > 1
However, it throughs the following error:
Msg 8120, Level 16, State 1, Line 1
Column 'HlthPlan.HMOID' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.*
I am fairly new to SQL and any suggestions would be appreciated.
Don't include * for your select query. Only include the columns that you are using in GROUP BY
SELECT HMO1A, HMONM, COUNT(*) from HlthPlan
GROUP BY HMO1A, HMONM
HAVING COUNT(*) > 1;
With only three columns to check, assuming non-null values across a single row:
select * from HlthPlan
where Addon10 in (Addon15, Addon20) or Addon15 = Addon20
You can also use cross apply to pivot the values for grouping:
select HMOID, addon
from HlthPlan cross apply (
select addon
from (values (Addon01), (Addon02), (Addon03), ... (Addon20)) as pvt(addon)
) a
where addon is not null
group by HMOID, addon
having count(*) > 1;
http://rextester.com/QWIW87618
You'll get multiple rows for each HMOID where the are different groups of columns having the same value. By the way, reporting on the names of specific columns involved would add another degree of difficulty to the query.
One way you can check for this is using UNPIVOT to compare your results:
create table #hmo (hmoid varchar(6), name varchar(25), Addon10 varchar(25),
Addon15 varchar(25), addon20 varchar(25));
insert into #hmo
values ('RFFF', 'Blah','img path1', 'img path2', 'img path1');
select hmoid, name, addval, addcount = count(adds)
FROM #hmo
UNPIVOT
(
addval FOR adds IN
(addon10, addon15, addon20)
) as unpvt
group by hmoid, name, addval having count(*) > 1
Will give results:
hmoid name addval addcount
RFFF Blah img path1 2
This way you can check against every row in the table and will see any row that has any two or more columns with the same value.
This does have the potential to get tedious if you have a lot of columns; the easiest way to correct for that is to build your query dynamically using info from sys.tables and sys.columns.

How to join two tables based on Grouping of 1 column in both the tables

I have come up a situation which is not easy to explain in sentence so i will go ahead and give the complete scenario here.
I have one result set like the below :-
It shows header_equipment_id(s) in a group of jil_equipment_id,relationship_name,cell_group.. For example 3159398,4622903 lies in one group.
The other result set is given below, This is the table where i want to update 3 columns namely Is_Applicable_Price,prc_content_rid,prc_type_name
If you notice clearly, You will find the same header_equipment_id column here. If you group it with the result found above, You will find 3 different groups for. But out of those 3 groups, one group is red, It is red because they belong to different cell_group/relationship_name.
**
Yellow and green are passed scenario and Red, Blue are fail.
**
I want to update the columns Is_Applicable_Price,prc_content_rid,prc_type_name if the Group of header_equipment_id(s) fall under the same cell_group and relationship_name.
So the final result set would look something like below -
Please help me with any inputs if possible. It's a situation where i know one single query won't work. But i will need to have multiple Temp tables for the transformation. But this is the shortest i have came across.
I am using Microsoft sql server 2012.
Please help. Even a small hint would be of great help to me. Thanks in advance.
It seems that the only thing the 2 tables have in common is that a cell_group can have a one or more rows of header_equipment_id. If we can generate a unique value based on header_equipment_id then we can join the 2 tables on this value. Note I have used a simple division , you may wish to check that this method is unique enough for your purposes.
/*create table a
(jil_equimentid int,relationship_name varchar(20),header_equipment_id int,
smart_equipment_id int,cell_group int,new_price_flag int,is_applicable_price int,prc_content_rid int,prc_type_name varchar(20))
truncate table a
insert into a values
(1282977,'default',3159398,1282977,3,1,1,106347924,'New Price'),
(1282977,'default',4622903,1262578,3,1,1,106347924,'New Price'),
(1282977,'default',1659861,1282977,6,1,1,106347925,'New Price'),
(1282977,'default',4622904,1282977,6,1,1,106347925,'New Price')
go
drop table t
go
create table t
(jil_equimentid int,relationship_name varchar(20),header_equipment_id int,
smart_equipment_id int,cell_group int,new_price_flag int,is_applicable_price int,prc_content_rid int,prc_type_name varchar(20))
truncate table t
insert into t values
(1282977,'128297711111 default',4622903,1282977,1,1,null,null,null),
(1282977,'128297711211 default',3159398,1262578,2,1,null,null,null),
(1282977,'128297712111 default',4622904,1282977,4,1,null,null,null),
(1282977,'128297712211 default',1659861,1282977,5,1,null,null,null),
(1282977,'128297711101 default',3159398,1262578,1,1,null,null,null),
(1282977,'128297711101 default',4622903,1282977,1,1,null,null,null),
(1282977,'default' ,3159398,1262578,2,1,null,null,null),
(1282977,'default' ,4622903,1282977,2,1,null,null,null),
(1282977,'128297711101 default',1659861,1262577,3,1,null,null,null),
(1282977,'128297711101 default',4622904,1282977,3,1,null,null,null),
(1282977,'default' ,1659861,1262577,4,1,null,null,null),
(1282977,'default' ,4622904,1262577,4,1,null,null,null)
*/
DROP TABLE #TEMPA;
;WITH CTE AS
(SELECT a.cell_group,
sum(a.header_equipment_id / 10000000.0000) uniqueval
from a
group by a.cell_group
)
SELECT DISTINCT CTE.UNIQUEVAL ,IS_APPLICABLE_PRICE ,PRC_CONTENT_RID ,PRC_TYPE_NAME
INTO #TEMPA
FROM CTE
JOIN A ON A.CELL_GROUP = CTE.CELL_GROUP
;WITH CTE AS
(
SELECT t.relationship_name,t.cell_group,
sum(t.header_equipment_id / 10000000.0000) uniqueval
from t
group by t.relationship_name,t.cell_group having count(*) > 1
)
SELECT T.*,CTE.UNIQUEVAL,ta.*
FROM CTE
JOIN T ON T.RELATIONSHIP_NAME = CTE.RELATIONSHIP_NAME AND T.CELL_GROUP = CTE.CELL_GROUP
join #tempa ta on ta.uniqueval = cte.uniqueval

PostgreSQL Inserted rows differ from select

I have a problem with an INSERT in PostgreSQL. I have this query:
INSERT INTO track_segments(tid, gdid1, gdid2, distance, speed)
SELECT * FROM (
SELECT DISTINCT ON (pga.gdid)
pga.tid as ntid,
pga.gdid as gdid1, pgb.gdid as gdid2,
ST_Distance(pga.geopoint, pgb.geopoint) AS segdist,
(ST_Distance(pga.geopoint, pgb.geopoint) / EXTRACT(EPOCH FROM (pgb.timestamp - pga.timestamp + interval '0.1 second'))) as speed
FROM fl_pure_geodata AS pga
LEFT OUTER JOIN fl_pure_geodata AS pgb ON (pga.timestamp < pgb.timestamp AND pga.tid = pgb.tid)
ORDER BY pga.gdid ASC) AS sq
WHERE sq.gdid2 IS NOT NULL;
to fill a table with pairwise connected segements of geopoints. When I run the SELECT alone I get the correct pairs, but when I use it in the statement above, then some are paired the wrong way or not at all. Here's what I mean:
result of SELECT alone:
tid;gdid1;gdid2;distance;speed
"0f6fd522-5f1e-49a4-b85e-50f11ef7f908";10;11;34.105058803;31.0045989118182
"0f6fd522-5f1e-49a4-b85e-50f11ef7f908";11;12;90.099603143;14.7704267447541
"0f6fd522-5f1e-49a4-b85e-50f11ef7f908";12;13;23.331326565;21.2102968772727
result after INSERT with the same SELECT:
tid;gdid1;gdid2;distance;speed
"0f6fd522-5f1e-49a4-b85e-50f11ef7f908";10;12;122.574;17.2639603638028
"0f6fd522-5f1e-49a4-b85e-50f11ef7f908";11;12;90.0996;14.7704267447541
"0f6fd522-5f1e-49a4-b85e-50f11ef7f908";12;13;23.3313;21.2102968772727
What be the cause of that? It's exactly the same SELECT statement for the INSERT, so why does it give different results?
DISTINCT ON (pga.gdid) can pick any row from a set with equal pga.gdid. You can get different result even by execution the same query for several times. Add additional ordering to get consistent results. something like: pga.gdid ASC, pgb.gdid ASC
BTW You may want to order by pga.gdid ASC, pgb.timestamp - pga.timestamp ASC to get the "next" point.
BTW2 It may be easier to use lead() or lag() window functions to calculate differences between current row and next/previous. This way you wont need a self join and will likely get better performance.
You are ordering your query results only by the column pga.gdid, which is the same in all the rows, so postgres will order the results in a different way each time you do the select query.

Solving Duplicated in Access

i had a table depends on more than one tables and i get this final
ScrrenShoot have a look in picture
i need to choose from values if firstdate duplicated in specific criteria
for ex . i need one row for 18.2.2016 / max value ( get the greater one ) / min value (get the less one )
You need to provide us with better information, but here is what I think you're looking for.
You need a separate query for each min/max value you want to find. Where you see "MyTable" you need to replace it with the object name shown in the screenshot.
Query 1 "Max"
SELECT MyTable.FirstOfDate, Max(MyTable.MaxValue) AS MaxOfMaxValue
FROM MyTable
GROUP BY MyTable.FirstOfDate;
Query 2 "Min"
SELECT MyTable.FirstOfDate, Min(MyTable.MinValue) AS MinOfMinValue
FROM MyTable
GROUP BY MyTable.FirstOfDate;
Query 3 "Merge"
SELECT DISTINCT MyTable.FirstOfDate, Max.MaxOfMaxValue, Min.MinOfMinValue
FROM (MyTable
INNER JOIN [Max] ON MyTable.FirstOfDate = Max.FirstOfDate)
INNER JOIN [Min] ON MyTable.FirstOfDate = Min.FirstOfDate
GROUP BY MyTable.FirstOfDate, Max.MaxOfMaxValue, Min.MinOfMinValue;

Resources