SQL
SQL
create table TEST (col1 int primary key identity(1,1) not null,
col2 varchar(50) not null,
col3 money not null,
BillDate datetime default GetDate())
--Add/Insert values into TEST table
insert into TEST(col2,col3,BillDate) values ('EXTE. HD' , 4500, '03-23-2015 15:5
0:00.345')
Select * from TEST
-- 2. insert to skip a nullable column
Insert into TEST(col2,col3) values ('USB 4.0', 5500)
Select * from TEST
-- 3. Insert to add a new row
Insert Into TEST(col2,col3,BillDate) values('SEAGATE', 7000, GETDATE())
SP_HELP TEST
Insert Into TEST(col2,col3,BillDate) values('DELL', 7000, GETDATE()), ('USB 3.0'
, 3500, GETDATE()), ('USB 5.0', 9500, GETDATE())
--update to modify record
update TEST set col2='Seagate 1 TB' where col1=3
-- delete a particular row or a record
Delete from TEST where col1=6
-- drop a table
select DeptId, count(*) as 'Number of people working in same dept' from Employee
s group by deptId
Select DeptId, min(salary) as ' employee with lowest pay in department' from Emp
loyees group by DeptId order by min(salary) desc
-- displaying results of two or more columns into one
select EmpCode, salary as 'gross sal', salary * .10 as 'Allowances' , salary * 0
.15 as 'TA', salary * 0.07 as 'Deductions' , salary+(salary * 0.10) + (salary *
0.15) - (salary * 0.07) as 'Net Salary'from Employees
-- Date functions
select getDate() as 'current date'
--1. Day()
select day(getDate()) as 'Day of current Date'
--2. Month()
select month(getDate()) as 'month of current Date'
--3. year()
select year(getDate()) as 'year of current Date'
--4. dateadd(datepart,number,date)
select dateadd(d,5,getDate()) as ' days after 5 days from today'
select dateadd(m,-5,getdate()) as ' date before 5 months from today'
-- combining or concatenating two or more expressions into one column
select EmpCode+' Gets a salary of Rs.' + STR(salary,10,2) + ' and works for Dept
=' + STR(DeptId,3,2) from Employees
-- upper
select upper(EmpName) from Employees
select Ltrim('
-- nested subquerry
select empcode, empname, deptid from employees where deptid in (select deptid fr
om departments where loc_id in
(select loc_id from locations where locations = 'chennai'))
-- correlated subquerry
select dname from departments where deptid in (select deptid from employees wher
e departments.deptid = employees.deptid)
select * from employees
select * from Departments
select * from locations
-- list of employees who are working under manager E-002
update employees set mgr_id = 'E-002' where empcode = 'E-005'
select empcode, empname, deptid from employees where mgr_id ='E-002'
select empcode,empname from employees where deptid in (select deptid from employ
ees where departments.deptid = employees.deptid)
-- cube operator
-- 1. without cube
select empname, deptid, count(*) as total from employees group by empname, dept
id order by empname, deptid desc
-- this is not a valid summary hence we use cube operator
--2. with cube
select empname, deptid, count(*) as total from employees group by empname, depti
d with cube
-- rollup operator
select deptid, count(*) from employees group by deptid with rollup
-- assignment 1
select mgr_id, salary from employees where salary in (select min(salary) from em
ployees group by mgr_id) and salary > 16000 and mgr_id is not null
--assignmnet 2
select count(distinct mgr_id) from employees where mgr_id is not null
-- assignmnet 3.
select mgr_id, count(*) from employees where mgr_id is not null group by mgr_id
select * from employees
select * from Departments
--raiseerror statement
create proc dispdetails
@tname varchar (10)
as
if (select count(*) from sys.objects where type = 'U' and name = @tname) >0
begin
select * from sys.objects where type = 'U' and name = @Tname
end
else
begin
raiserror ('server error: %s - Table %s does not exists', 15,1,@@servern
ame, @tname)
end
exec dispdetails 'EMPloyees'
begin catch
print 'error occured is:'
set @msg = (select error_severity())
print @msg
end catch
--Try_convert and try_parse
SELECT
CASE WHEN try_convert(float, 'test') is null
then 'cast failed'
else 'cast succeeded'
end as result
go
set dateformat mdy;
select try_convert (datetime2, '12/31/2014') as result;
go
--try_parse
select try_parse ('1' as int)
select try_parse ('B' as int)
--try_catch
use eClerxDb
go
begin try
--table does not exists, object name resolution error
--error not caught
declare @num int
set @num = 5/0
end try
begin catch
select
error_number() as errornumber, error_severity() as errorseverity, error_state()
as errorstate, error_procedure() as errorprocedure, error_line() as errorline, e
rror_message() as errormessage
end catch
go
--xact_abort example
use eClerxDb
go
if object_id('tab2', 'U') is not null
drop table tab2
go
if object_id('tab1', 'U') is not null
drop table tab1
go
create table tab1
(A int not null primary key)
create table tab2
(A int not null references tab1(A))
go
insert into tab1 values(1), (3), (4), (6)
go
set xact_abort off;
go
begin transaction
insert into tab2 values
insert into tab2 values
insert into tab2 values
commit transaction
go
set xact_abort on;
begin transaction
insert into tab2 values
insert into tab2 values
insert into tab2 values
commit transaction
go
(1)
(2)
(3)
(4)
(5)
(6)
-- select shows only keys 1 and 3 added...key 2 inserted failed and will roll ba
ck but since xact_abort was off and rest of transaction will succeed
-- key insert error with xact_abort on will cause all of the second trans to rol
lback
select * from tab2
go
--user defined functions
--1. function with single parameter
create function fnGetEmpname (@fullname varchar(50))
returns varchar(30)
as
begin
return (select @fullname)
end
--1.a calling a function
select dbo.fnGetEmpname(empname)
as name, salary from employees
--2. function with two parameters
create function fnGetEmpname2 (@empcode varchar(50), @fullname varchar(30))
returns varchar(45)
as
begin
return (select @empcode + ':' + @fullname)
end
--2.a calling function
select dbo.fnGetEmpname2(empcode,empname)
as name, salary from employees
use eClerxDb
go
if object_id('fnGetEmpname2', 'FN') is not null
drop function fnGetEmpname2
go
--After trigger
if object_id('Empdetails_trigger','tr') is not null
drop trigger Empdetails_trigger
go
create trigger Empdetails_trigger
on employees
after delete, insert, update
as
begin
if @@rowcount = 0
return;
set nocount on;
select count (*) as insertedcount from inserted
select count (*) as deletedcount from deleted
end
insert into employees
values ('E-007', 'Rahul K', '22000', '30', 'E-001')
delete from employees where empcode ='E-007'
--insert trigger for departments table
if object_id('check_dname','tr') is not null
drop trigger check_dname
go
create trigger check_dname
on departments
for insert
as
if (select count(*) from inserted where dname like '%[0-9]%')>0
begin
select 'department name cannot contain numbers'
rollback transaction
select 'inserted failed'
end
else
begin
select 'record inserted'
end
-- to execute above trigger
insert into departments(dname, loc_id) values ('fin10', 130)
--update trigger
create table deposits (depname varchar (20), depdate datetime, amt float)
insert into deposits values ('aaa', getdate(), 30000), ('BBB', dateadd(dd, -5, g
etdate()), 41000)
create trigger amt_check on deposits
for update
as
if(select amt from inserted )<25000
begin
print 'new amount cannot be less than 25000. update failed'
rollback transaction
-- if we do not menti
on roll back, message will get printed although it will update
end
else
begin
print 'update successful'
end
update deposits set amt=35000
where depname ='AAA'
-- Instead of trigger
-- The code in an INSTEaD OF trigger is executed in place of original DML statem
ent
create TABLE books(bookcode int primary key not null identity (100,1), bookname
varchar (50) not null, authors varchar (50) not null)
Insert into books(bookname, authors) values ('QUERING SQL 2012','aaa'), ('Java
EE', 'BBB'), ('C#.net', 'CCC'), ('XML', 'DDD')
select * from books
use eClerxDb
go
if object_id('books_trigger','tr') is not null
drop trigger books_trigger
go
create trigger books_trigger
on books
with encryption
instead of insert
as
if (select count(*) from books where bookname = (select bookname from inserted))
>0
begin
select 'duplicate book name found updating the book.'
update books set authors = (select authors from inserted) where booknam
e = (select bookname from inserted)
end
else
begin
insert into books (bookname, authors)
select bookname, authors from inserted
select 'record inserted'
end
use eClerxDb
go
if object_id('casdeltrigger','tr') is not null
drop trigger casdeltrigger
go
create trigger casdeltrigger
on master
for delete
as
if (select count(*) from newdeposits where code = (select code from deleted)) >0
begin
delete from newdeposits where code = (select code from deleted)
print 'cascade delete successful. child records deleted'
end
else
begin
print 'no child record found. record deleted from master table'
end
delete from master where code = 101
select * from newdeposits
-- create a trigger on the 'employees' table which allows the user to insert a r
ecord only if the salary of the new record is more than 4000.
use eClerxDb
go
if object_id('employee_4000','tr') is not null
drop trigger employee_4000
go
create trigger employee_4000
on employees
for insert
as
if (select count(*) from inserted where salary > 4000)>0
begin
select 'found employee with salary more than 4000'
select 'inserted successful'
end
else
begin
select 'insert failed'
rollback transaction
end
insert into employees values ('E-009' , 'rounak V', 10000, 10, 'E-001')
select * from employees
-- create a trigger for departments table which allows user to insert only 2 rec
ords at a time
use eClerxDb
go
if object_id('dept','tr') is not null
drop trigger dept
go
create trigger dept
on departments
for insert
as
if (select count(*) from inserted) >2
begin
select 'records cannot be added. only 2 allowed'
rollback transaction
select 'inserted failed'
end
else
begin
select 'insert successful'
end
insert into departments( dname, loc_id) values ( 'xxx', 120), ( 'YYY', 130), ('z
zz', 110)
insert into departments( dname, loc_id) values ( 'xxx', 120), ( 'YYY', 130)
select * from departments
delete from departments where deptid = 130
-- cursor
/* syntax for declaring a cursor.
declare <cursor_name>
cursor
for
<select statement>
-- 6.cursor with forward only ... this moves in forward direction only...prior w
ont work here
set nocount on
declare @code varchar (5)
declare @name varchar (20)
declare forward_cur_emp cursor forward_only
for
select empcode, empname from employees order by empname
open forward_cur_emp
if @@cursor_rows >0
begin
fetch next from forward_cur_emp into @code, @name
while @@fetch_status = 0
begin
if @name = 'Rajesh V'
update employees set salary = 24000 where current of forward_cur_emp
fetch next from forward_cur_emp
into @code, @name
end
end
close forward_cur_emp
deallocate forward_cur_emp
set nocount off
go
select * from employees
sp_helptrigger employees
-- local temporary tables
create table #T1
( col1 int not null)
insert into #T1 values(10), (20)
select * from #T1
select name from tempdb.sys.objects where name like '#%'
drop table #t1
-- temporary tables with transactions
create table #T1
( col1 int not null)
begin transaction
insert into #t1 values (10), (20)
rollback transaction
select col1 from #T1
drop table #T1
-- XML type
--1. XML raw
select * from employees
for XML raw
--2. XML auto
select * from Employees for XML auto
--3. XML auto, elements
select * from employees for XML auto, elements
--4. XML auto, elements, root
select * from employees for XML auto, elements, root ('emps')
-- 5. Xpath query
Select deptid, dname as 'department1' from departments where deptid in (10,30) o
rder by deptid for xml path ('departments'), root ('depts')
-- Xquery methods
declare @xml XML
set @xml = '<suppliers> <user userno="1" email="sams@gmail.com">
<item no="1" name="usb 2.0"></item>
<item no="2" name="usb 3.0"></item> </user>
<user userno="2" email="john@gmail.com">
<item no="1" name="usb 4.0"></item>
</user>
<user userno="3" email="smith@gmail.com">
<item no="1" name="HDD 1TB"></item>
</user>
<user userno="35" email="jams@gmail.com">
<item no="2" name="HDD 2 TB"></item>
</user>
<user userno="4" email="tango@gmail.com">
<item no="3" name="HDD 4 TB"></item>
</user>
</suppliers>'
--1.xml.exist()
-- this method returns a boolean value depending on the conditions as :
select @xml.exist('/suppliers/user[@email="sams@gmail.com"]') as result1
select @xml.exist('/suppliers/user[@email="dams@gmail.com"]') as result2
-- 2. Xml.querry()
--this method takes an xquery statement and returns an instance of XML datatype
select @xml.query('/suppliers/user') as users
-- display unique values for representing item nos. from @xml
select @xml.query('distinct-values(data(/suppliers/user/item/@no))') as items
--3. xml.value()
--this method takes an xquery statement after type casting
select @xml.value('/suppliers[1]/user[1]/@email', 'varchar(20)') as resultemail1
select @xml.value('/suppliers[1]/user[2]/@email', 'varchar(20)') as resultemail2
--4. xml.nodes()
-- this method takes an xquery statement and returns a single value after type c
asting
select x.value('@userno','int') as userno, x.value('@email','varchar(20)') as em
ail
from @xml.nodes('/suppliers/user') tempxml(x)
select x.value('../@userno','int') as userno,
x.value('../@email','varchar(50)') as email,
x.value('@name','varchar(20)') as itemname
from @xml.nodes('/suppliers/user/item') tempxml(x)
--30/06/2015
-- INDEXES
select * from EmpAsXML
-- Sample data
create table XML_Table
(ID int identity (1,1) not null, customername varchar(50) null, customerphone va
rchar (50) null, customeraddress xml null,
constraint [ID_PK_XML] primary key([ID] asc))
-- insert data into xml_table
insert into xml_table(customername, customerphone, customeraddress)
values ('sam Smith','022-8845',
'<customer>
<address1>Marine Drive</address1>
<city>Mumbai</city>
<state>Mah</state>
<zip>400001</zip>
</customer>')
insert into xml_table(customername, customerphone, customeraddress)
values('Jean D','011-884578',
'<customer>
<address1>Connaught</address1>
<city>Delhi</city>
<state>ND</state>
<zip>909011</zip>
</customer>')
select * from xml_table
-- XML INDEXES
create primary XML index [PK_XML_DATA_customeradd]
on xml_table(customeraddress)
-- disable index
alter index [PK_XML_DATA_customeradd] on xml_table disable
-- droping index
drop index [PK_XML_DATA_customeradd] on xml_table
sp_help xml_table
-- OPEN XML
--1. open XML
declare @idoc int, @doc varchar(1000)
set @doc ='<root>
<customer customerid ="vinet" contactname ="Paul Henry">
<order customerid ="vinet" employeeid ="5" orderdate="2014-07-06T15:20:37">
<orderdetail orderid="1024" productid="10" quantity="12"/>
<orderdetail orderid="1024" productid="22" quantity="10"/>
</order>
</customer>
<customer customerid ="gloss" contactname ="carlos gonzel">
<order customerid ="gloss" employeeid ="3" orderdate="2015-06-06T19:25:37">
<orderdetail orderid="1028" productid="70" quantity="3"/>
</order>
</customer>
</root>'
-- 2.create an internal representation of xml doc
exec sp_xml_preparedocument @idoc output, @doc
-- now this i
-- partition functions
select deptid, row_number() over (partition by deptid order by empcode) as 'rown
um',
empname from employees
select * from employees
select * from departments
select distinct deptid, sum(salary) over (partition by deptid order by deptid)
as 'total salary' from employees
-- group by versus partition by clause
-- Assignment 1. write a cursor which will target deptid 10 and 30 and fetch var
ious actions for showing first, last, next and previous records
declare cur3 cursor
scroll
for
select * from employees where deptid in (10,30) order by deptid
open cur3
select 'result of fetch first'
fetch first from cur3
select 'result of fetch last'
fetch last from cur3
select 'result of fetch prior'
fetch prior from cur3
select 'result of fetch next'
fetch next from cur3
close cur3
deallocate cur3
create table #CandidateTable1 (CandidateId int primary key not null, CandidateNa
me varchar(50), CandidateAddress xml)
insert into #CandidateTable1 values (1,'john', '<candidate><address>airoli</add
ress> <city>Mumbai</city><phoneno>123456</phoneno></candidate>'),
(2,'robert','<address>rabale</address> <city>Mumbai</city><phoneno>987654</phone
no>')
select * from #CandidateTable1
declare @idoc int, @doc varchar(1000)
set @doc ='<root>
<candidate address ="Airoli" city ="mumbai" phoneno="123456">
</candidate>
<candidate address ="rabale" city ="mumbai" phoneno="987654">
</candidate>
</root>'
-- create an internal representation of xml doc
-- now this i
-----------------alternative method--------------------------create table #CandidateTable (CandidateId int primary key not null, CandidateNam
e varchar(50), CandidateAddress xml)
insert into #CandidateTable values (1,'john', '<address>airoli</address> <city>
Mumbai</city><phoneno>123456</phoneno>'),
(2,'robert','<address>rabale</address> <city>Mumbai</city><phoneno>987654</phone
no>')
select CandidateAddress.value ('city[1]','varchar(50)') as city ,
candidateAddress.value ('phoneno[1]','int') as phoneno from #candidatetable
--5. smalldatetimefromparts
declare @year int = 2015, @month int = 06, @day int = 30, @hour int = 11, @min i
nt = 40
select smalldatetimefromparts (@year,@month,@day,@hour,@min) as [smalldatetimefr
omparts]
--6. datetimeoffset
declare @datetimeoffset datetimeoffset(4) ='12-10-25 12:32:10 + 01:00'
declare @date date = @datetimeoffset
select @datetimeoffset as '@datetimeoffset', @date as '@date'
--7. datetime2fromparts
declare @year int = 2015, @month int = 06, @day int = 30, @hour int = 11, @min i
nt = 40, @sec int = 59
select datetime2fromparts (@year, @month, @day, @hour, @min, @sec, 500, 3) as [r
etrieved data from datetime2fromparts]
select sysdatetime() -- datetime2 datatype
select getdate ()
-- datetime datatype
select eomonth(sysdatetime()) as end_of_currentmonth
-- format function
--1. formatting the date (display datename, month name and day in year)
declare @date datetime ='07/01/2015'
select format(@date, 'D','en-US') as formatteddate
--2. display long date and time function
declare @date datetime =getdate()
select format(@date, 'yyyy/MM/dd hh:mm:ss tt','en-US') as formatteddate
-- Throw statement
-- perform a check
declare @unitprice money, @discount numeric (4,3)
select @unitprice = 5
select @discount = .6
end
exec pagination_2 100
--3.c pagination with offset filter
create proc pagination_3
(@start int =1)
as
begin
select DummyId, Name, Details from #DummyTable order by DummyId
offset @start rows fetch next 10 rows only
end
exec pagination_3 1000
--3.d
create proc pagination_4
(@start int = 1, @end int=1 )
as
if (@end <100)
begin
select DummyId, name, details from #DummyTable where DummyId between @start and
@end order by DummyId
end
else
begin
throw 50000, 'end point should be less than 100',1
end
exec pagination_4 1, 50
drop proc pagination_4
-- execute sp_executesql
exec sp_executesql
N' select * from #DummyTable where DummyId = @id',
N' @id int',
@Id = 500
-- parametrize query with SQL string
declare @v int
declare @s nvarchar (500)
declare @p nvarchar(500)
--1.a build the sql string
set @s = N' select deptid, empcode, salary from employees where deptid = @deptid
'
set @p = N' @deptid int'
--1.b setting the value for parameter integer
set @v = 10
--spartial datatypes
/*
describes physical location and shape of geometry objects. These objects can be
point, locations such as roads, lakes, countries etc.
Two spatial datatypes supported in sql are geometry and geography.
circular string - is an object of type geometry which is defined by 3 points i.e
. startpoint, endpoint, anchor point (lies in between end and start point)
*/
-- 1. example of circular string
declare @gm geometry
set @gm = geometry :: STGeomFromText ('CIRCULARSTRING(2 0, 1 1, 0 0)', 0)
select @gm
--2. another example
declare @g geometry = 'CIRCULARSTRING(1 1, 2 0, -1 1)'
select @g
--3. closed circular string
declare @g geometry
set @g = geometry::Parse('CIRCULARSTRING(2 1, 1 2, 0 1, 1 0, 2 1)')
select @g
--4. compound curve
/*
--4. compound curve - a single continued path that connects a set of points. E
ach pair of points can be linear or curved.
-- the parameters are
1)linestring (determined by circular string),
2)circular string,
each linestring and circular string segment must begin at the point where previo
us segment ended.
*/
declare @g geometry = 'compoundcurve (circularstring (1 0, 0 1, -1 0), (-1 0, 1.
25 0))'
select @g
--curved polygon with 5 points
declare @g geometry ='curvepolygon((4 2,8 2, 8 6, 4 6, 4 2))'
select @g
--curved polygon with gepgraphy
declare @g geography
set @g = 'curvepolygon(circularstring(-122.358 47.653, -122.348 47.649, -122.348
--create procedure
create proc GetSalesOrder
As
Begin
select OrderId, CustomerCode, OrderDate, TotalAmount from SalesOrder
end
--result of proc without "with resultsets"
exec GetSalesOrder
-- return column namesorderId, CustomerCode, OrderDate and TotalAmount to OrderI
d, CustCode, OrderDate and Amount
exec GetSalesOrder
with Result Sets
((
OrderId int,
CustCode varchar(20),
OrderDate varchar(10),
Amount float))
-- the default option for execute statement is "with result sets undefined"
exec GetSalesOrder
with result sets undefined
--Execute statement "with resultsets none" option
-- this will not return a result
create proc noresult
As
Begin
print 'This is a test'
end
exec noresult
with result sets none
-- with existing procedure GetSalesOrder
exec GetSalesOrder
with result sets none
-- multiple resultsets defining two results
create procedure GetEmpDeptTwoResultSet
as
Begin
select EmpCode, EmpName, Salary, Deptid from employees
select Deptid, Dname from departments
End
execute GetEmpDeptTwoResultSet
with result sets
(
(
ECode varchar(5),
Name varchar (30),
Salary money,
deptid int),
(
deptid int,
department varchar (20))
)
-- Parse conversion function
/*
PARSE(String_value AS data_type [USING CULTURE])
nal
*/
culture is optio
e table
--create a sequence object viz; invoice number that will start from seed -1000 a
nd increment by 5 every time whenever sequence object is accessed
use eClerxDb
go
create Sequence InvoiceNumber
as INT
start with 1000
increment by 5
--let's use the sequence with next value for clause
select next value for InvoiceNumber
-- sequence generated now will use it when inserting rows into a table
use eClerxDb
go
if OBJECT_ID ('NewInvoice','U') is not null
BEGIN
DROP TABLE NewInvoice
END
BEGIN
CREATE TABLE NewInvoice (InvoiceId INT null, name VARCHAR(1000) null)
END
--Insert values
INSERT INTO NewInvoice VALUES (
next value for InvoiceNumber, 'PATRICK N')
INSERT INTO NewInvoice VALUES (
next value for InvoiceNumber, 'McGraw')
select * from NewInvoice
drop table NewInvoice
drop sequence InvoiceNumber
-- The current value of sequence
select current_value from sys.sequences where name ='InvoiceNumber'
next
next
next
next
next
next
next
value
value
value
value
value
value
value
for
for
for
for
for
for
for
RECYCLE_Sequence
RECYCLE_Sequence
RECYCLE_Sequence
RECYCLE_Sequence
RECYCLE_Sequence
RECYCLE_Sequence
RECYCLE_Sequence
next
next
next
next
value
value
value
value
for
for
for
for
NewSequence
NewSequence
NewSequence
NewSequence
Create a sequence CountBy1 which starts with 10, adds by 10 and recycles from 1
Then add a table MyOrders with columns
OrderId int not nullable PK,
Custid int not nullable with a check constarint that custid >0
Empid int not null with a check constarint that empid >0
orderdate date not null
1. Insert rows for the table above with orderid mapped to sequence
2. Rows inserted should be shown in stored procedure where new column sets shoul
d be created with new column names as order_id, customer_id, EmployeeId and Ordd
ate
*/
create Sequence CountBY1
As int
Start with 10
increment by 10
minvalue 1
maxvalue 50
cycle
select
select
select
select
select
select
select
next
next
next
next
next
next
next
value
value
value
value
value
value
value
for
for
for
for
for
for
for
CountBY1
CountBY1
CountBY1
CountBY1
CountBY1
CountBY1
CountBY1
-- Contained database
use Master
GO
Sp_configure 'SHOW ADVANCED options',1
GO
RECONFIGURE WITH OVERRIDE
GO
SP_CONFIGURE 'Contained database authentication',1
GO
RECONFIGURE WITH OVERRIDE
GO
SP_CONFIGURE 'Show advanced option',0
GO
RECONFIGURE WITH OVERRIDE
GO
check_policy = off
go
avg(UnitPrice) as AvgUnitPrice,
Sum (OrderQty) as SumOrderQty
from MySalesOrderDetails group by ProductId order by ProductId
-- create column store index
create nonclustered columnstore index [CIX_MySalesOrderDetails_ColumnStore] on M
ySalesOrderDetails (UnitPrice, OrderQty, ProductId)
--view/select the table with columnstore index
select ProductId, SUM(UnitPrice) as SumUnitPrice, Avg(UnitPrice) as AvgUnitPrice
, SUM (OrderQty) as SumOrderQty, Avg (OrderQty) as AvgOrderQty
from MySalesOrderDetails group by ProductId Order by ProductId