SQL Server: aggregate error on grouping - sql

I have a table called tasks, which lists different tasks a worker can complete. Then i have a relationship table that links a completed task to a worker.
I'm trying to write query that groups the tasks into a list based on the worker id, but the query gives me the following error (see below).
Column 'mater.dbo.worker_task_completion.FK_task_id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Tables
CREATE TABLE [dbo].[tasks]
(
[task_id] [int] IDENTITY(1,1) NOT NULL,
[name] [nvarchar](50) NOT NULL,
[icon] [nvarchar](max) NULL,
[isActive] [int] NOT NULL,
[time] [int] NOT NULL,
CONSTRAINT [PK_tasks] PRIMARY KEY CLUSTERED
(
[task_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
CREATE TABLE [dbo].[worker_task_completion]
(
[FK_worker_id] [int] NOT NULL,
[FK_task_id] [int] NOT NULL,
[update_date] [datetime] NOT NULL,
CONSTRAINT [PK_worker_task_completion] PRIMARY KEY CLUSTERED
(
[FK_worker_id] ASC,
[FK_task_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Query
SELECT top 100 wtc.FK_worker_id,
tasks = Stuff((SELECT ', ' + dbo.tasks.NAME
FROM dbo.tasks
WHERE dbo.tasks.task_id =
wtc.FK_task_id
FOR xml path ('')), 1, 1, '')
FROM dbo.worker_task_completion AS wtc
LEFT JOIN dbo.tasks AS tc
ON tc.task_id = wtc.fk_task_id
-- WHERE wtc.FK_worker_id IN ()
GROUP BY wtc.FK_worker_id

Hmmm. You cannot use a non-aggregated column for the correlation clause. The solution is to move the JOIN into the subquery:
SELECT top 100 wtc.FK_worker_id,
stuff((SELECT ', ' + t.NAME
FROM dbo.worker_task_completion wtc2 JOIN
dbo.tasks t
ON t.task_id = wtc2.FK_task_id
WHERE wtc2.FK_worker_id = wtc.FK_worker_id
FOR xml path ('')
), 1, 2, ''
) as tasks
FROM (SELECT DISTINCT wtc.FK_worker_id
FROM dbo.worker_task_completion wtc
) wtc
-- WHERE wtc.FK_worker_id IN ()
Note that I changed the second argument for STUFF(). Presumably, you want to remove the space as well as the comma.

;WITH CTE_worker_task_completion
AS (SELECT [FK_worker_id]
,[FK_task_id]
FROM [dbo].[worker_task_completion])
------------------------------------------
SELECT [WT].[FK_worker_id]
,[Task]=Stuff(
(
SELECT ', '+[T].[Name]
FROM [dbo].[tasks] AS [T]
INNER JOIN CTE_worker_task_completion AS [WTC]
ON [T].[Task_ID]=[WTC].[Task_ID]
Where [WT].[Worker_ID]=[WTC].[Worker_ID]
ORDER BY [T].[Name] FOR XML PATH('')
),1,1,'')
FROM CTE_worker_task_completion AS [WT]
GROUP BY [WT].[FK_worker_id];

Related

Pivot while changing data types (dynamically)

Let's say I have 3 tables: users, customattributes, and customattributevalues. End user can add custom attributes by selecting a name and type for the attribute, and the edit the values for any user.
Here are my users:
id
firstname
lastname
active
datecreated
username
email
3
Ellen
Ripley
1
3/25/2235
78439
Rip8439#Weyland-Yutani.com
5
Johnny
Rico
1
4/16/2675
Roughneck31
RicoJ31#Roughnecks.com
customattributes (can be added to anytime)
id
fullname
uniquename
type
1
Hire Date
hiredate
date
2
Employee ID
eeid
int
3
Supervisor
supervisor
nvarchar(50)
4
Assigned Ship
assignedship
nvarchar(50)
5
Job Title
jobtitle
nvarchar(50)
type I currently have as sysname datatype.
customattributevalues (can be edited anytime)
id
attributeid
userid
value
1
1
3
2335-03-25
2
2
3
78439
3
3
3
Burke, Carter
4
4
3
Sulaco
5
5
3
Consultant
6
1
5
2675-04-16
7
2
5
78440
8
3
5
LT Rasczak
9
4
5
Rodger Young
10
5
5
Private
value I currently have as sql_variant datatype
So here is my question: how can I create a report that shows all employees and their attributes, 1 line per employee, without knowing how many custom attributes there are --and-- crucially, I want to explicitly convert each column to the correct data type
Desired output:
firstname
lastname
datecreated
username
email
Hire Date
Employee ID
Supervisor
Assigned Ship
Job Title
Ellen
Ripley
2235-03-25
78439
Rip8439#Weyland-Yutani.com
2335-03-25
78439
Burke, Carter
Sulaco
Consultant
Johnnie
Rico
2675-04-16
Roughneck31
RicoJ31#Roughnecks.com
2675-04-16
78440
LT Rasczak
Rodger Young
Private
I've already learned to do the dynamic column headers using dynamic queries, but it is the type conversion that is escaping me.
I'm adapting this solution for custom fields, but the limitation to this solution is you have to know each custom field to make the type conversion.
Here is what I've tried. I got the correct output, except for the type conversions.
Query:
DECLARE #columns NVARCHAR(MAX) = '';
DECLARE #sqlcmd NVARCHAR(MAX) = '';
SELECT #columns += QUOTENAME(fullname) + ','
FROM customattributesx ca
ORDER BY ca.id;
SET #columns = LEFT(#columns, LEN(#columns) - 1);
--PRINT #columns;
SET #sqlcmd = '
SELECT * FROM (
SELECT userid
,firstname
,lastname
,datecreated
,username
,email
,fullname
,value
FROM (
SELECT u.id as userid
,u.firstname
,u.lastname
,u.datecreated
,u.username
,u.email
,ca.id
,ca.fullname as fullname
,ca.uniquename
,ca.type
,cav.value as value
FROM dbo.users u
CROSS JOIN customattributesx ca
INNER JOIN customattributevaluesx cav
ON cav.attributeid = ca.id AND cav.userid = u.id
--ORDER BY u.id asc, ca.id asc
) t1
) t2
PIVOT (
MIN(value)
FOR fullname IN ('+#columns+')
) as pivottable
';
--print #sqlcmd
EXECUTE (#sqlcmd)
Create Tables:
USE [CTMS]
GO
/****** Object: Table [dbo].[users] Script Date: 11/24/2021 9:29:16 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[users](
[id] [int] IDENTITY(1,1) NOT NULL,
[firstname] [nvarchar](max) NULL,
[lastname] [nvarchar](max) NULL,
[active] [bit] NOT NULL,
[datecreated] [datetime2](7) NOT NULL,
[username] [nvarchar](256) NULL,
[email] [nvarchar](256) NULL,
[emailconfirmed] [bit] NOT NULL,
[passwordhash] [nvarchar](max) NULL,
[twofactorenabled] [bit] NOT NULL,
[lockoutend] [datetimeoffset](7) NULL,
[eockoutenabled] [bit] NOT NULL,
[accessfailedcount] [int] NOT NULL,
[qrcode] [nvarchar](50) NULL,
CONSTRAINT [PK_id] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY],
CONSTRAINT [uk_email] UNIQUE NONCLUSTERED
(
[email] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY],
CONSTRAINT [uk_qrcode] UNIQUE NONCLUSTERED
(
[qrcode] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY],
CONSTRAINT [uk_username] UNIQUE NONCLUSTERED
(
[username] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[users] ADD DEFAULT (getutcdate()) FOR [datecreated]
GO
USE [CTMS]
GO
/****** Object: Table [dbo].[customattributesx] Script Date: 11/24/2021 9:31:09 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[customattributesx](
[id] [smallint] IDENTITY(1,1) NOT NULL,
[fullname] [nvarchar](50) NOT NULL,
[uniquename] [nvarchar](50) NOT NULL,
[type] [sysname] NOT NULL,
CONSTRAINT [PK_customattributesx] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY],
CONSTRAINT [uk1_customattributesx] UNIQUE NONCLUSTERED
(
[uniquename] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
USE [CTMS]
GO
/****** Object: Table [dbo].[customattributevaluesx] Script Date: 11/24/2021 9:31:27 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[customattributevaluesx](
[id] [int] IDENTITY(1,1) NOT NULL,
[attributeid] [smallint] NOT NULL,
[userid] [int] NOT NULL,
[value] [sql_variant] NOT NULL,
CONSTRAINT [PK_customattributevaluesx] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY],
CONSTRAINT [uk1_customattributevaluesx] UNIQUE NONCLUSTERED
(
[attributeid] ASC,
[userid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[customattributevaluesx] WITH CHECK ADD CONSTRAINT [fk1_customattributesvaluesx] FOREIGN KEY([attributeid])
REFERENCES [dbo].[customattributesx] ([id])
GO
ALTER TABLE [dbo].[customattributevaluesx] CHECK CONSTRAINT [fk1_customattributesvaluesx]
GO
ALTER TABLE [dbo].[customattributevaluesx] WITH CHECK ADD CONSTRAINT [fk2_customattributesvaluesx] FOREIGN KEY([userid])
REFERENCES [dbo].[users] ([id])
GO
ALTER TABLE [dbo].[customattributevaluesx] CHECK CONSTRAINT [fk2_customattributesvaluesx]
GO
If you must convert the datatype (could really be a presentation layer thing), then a dynamic conditional aggregation should do the trick.
Example
Declare #SQL nvarchar(max) ='
Select U.*' +
(
Select concat(',',quotename(fullname),'=max(case when attributeid=',id,' then try_convert(',type,',value) end)')
From customattributes
For XML Path ('')
)+'
From users U
Join customattributesvalues V on U.ID=V.userid
Group By U.ID
,U.FirstName
,U.LastName
,U.active
,U.datecreated
,U.username
,U.email
'
--print #SQL
Exec(#SQL)
Results
The Generated SQL Looks Like This
Select U.*
,[Hire Date]=max(case when attributeid=1 then try_convert(date,value) end)
,[Employee ID]=max(case when attributeid=2 then try_convert(int,value) end)
,[Supervisor]=max(case when attributeid=3 then try_convert(nvarchar(50),value) end)
,[Assigned Ship]=max(case when attributeid=4 then try_convert(nvarchar(50),value) end)
,[Job Title]=max(case when attributeid=5 then try_convert(nvarchar(50),value) end)
From #users U
Join #customattributesvalues V on U.ID=V.userid
Group By U.ID
,U.FirstName
,U.LastName
,U.active
,U.datecreated
,U.username
,U.email
SQL_VARIANT can be cast to a destination data type.
Modify part of the dynamic query where you generate column list, to generate two lists. One list is for PIVOT part and the other for SELECT part where you cast you data types.
Example is based on the article you refer to in your question:
DECLARE #PivotList NVARCHAR( MAX )
DECLARE #SelectList NVARCHAR( MAX )
SELECT #SelectList = NULL, #PivotList = NULL
-- Column list with CAST e.g. CAST( eeid AS INT ) AS eeid
-- Data types come from your customattributes table
SELECT #SelectList = COALESCE( #SelectList + ',','') + 'CAST( ' + uniquename + ' AS [type] ) AS ' + uniquename,
-- Just a column list that goes into PIVOT operator
#PivotList = COALESCE( #PivotList + ',','') + uniquename
-- Your tables for attribute values and attribute type definitions
FROM customattributes AS ca
DECLARE #SQLQuery NVARCHAR(MAX)
SET #SQLQuery =
'SELECT StudID , '+#SelectList+'
FROM
( SELECT SM.StudID, S.SubjectName, SM.Score
FROM StudentMarks SM
INNER JOIN Subjects S
ON Sm.SubjectID = S.SubjectID
) AS tbl
PIVOT
( Sum(Score)
FOR SubjectName IN ('+#PivotList+') ) as pvt'
EXEC(#SQLQuery)

SQL select that generates a select query that automatically joins tables based on foreign key constraints?

Is it possible to write an SQL select statement that generates a SQL select statement that automatically joins multiple tables based on foreign key constraints?
I am interested in SQL Server databases in particular.
I have seen and used examples of queries that query sys.foreign_keys and sys.tables. I tried to add formulation of the SELECT statement here but I am aware this is not right for multi column key tables.
e.g.
select
schema_name(fk_tab.schema_id) + '.' + fk_tab.name as foreign_table,
'>-' as rel,
schema_name(pk_tab.schema_id) + '.' + pk_tab.name as primary_table,
substring(column_names, 1, len(column_names)-1) as [fk_columns],
substring(ref_column_names, 1, len(ref_column_names)-1) as [ref_columns],
fk.name as fk_constraint_name,
'SELECT * from ' + schema_name(pk_tab.schema_id) + '.' + pk_tab.name + ' A '
+ ' JOIN ' + schema_name(fk_tab.schema_id) + '.' + fk_tab.name + ' B '
+ ' ON ' + 'A.' + substring(ref_column_names, 1, len(ref_column_names)-1)
+ ' = ' + 'B.' + substring(column_names, 1, len(column_names)-1)
AS SelectStmnt
from
sys.foreign_keys fk
inner join
sys.tables fk_tab on fk_tab.object_id = fk.parent_object_id
inner join
sys.tables pk_tab on pk_tab.object_id = fk.referenced_object_id
cross apply
(select col.[name] + ', '
from sys.foreign_key_columns fk_c
inner join sys.columns col on fk_c.parent_object_id = col.object_id
and fk_c.parent_column_id = col.column_id
where fk_c.parent_object_id = fk_tab.object_id
and fk_c.constraint_object_id = fk.object_id
order by fk_c.constraint_column_id
for xml path ('') ) D (column_names)
cross apply
(select col.[name] + ', '
from sys.foreign_key_columns fk_c
inner join sys.columns col on fk_c.referenced_object_id = col.object_id
and fk_c.referenced_column_id = col.column_id
where fk_c.referenced_object_id = pk_tab.object_id
and fk_c.constraint_object_id = fk.object_id
order by fk_c.constraint_column_id
for xml path ('') ) E (ref_column_names)
order by
schema_name(fk_tab.schema_id) + '.' + fk_tab.name,
schema_name(pk_tab.schema_id) + '.' + pk_tab.name
I am interested in automatically generating SQL select statement that joins tables given say 2 table names of interest.
Example tables might be:
CREATE TABLE [dbo].[Project]
(
[Project_Code] [int] NOT NULL,
[Project_Name] [nvarchar](max) NULL,
[Department] [nvarchar](max) NULL,
PRIMARY KEY CLUSTERED
(
[Project_Code] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE TABLE [dbo].[Employee]
(
[Emp_Id] [int] NOT NULL,
[Emp_Name] [nvarchar](max) NULL,
[Manager_Id] [int] NULL,
[Project_Id] [int] NULL,
PRIMARY KEY CLUSTERED
(
[Emp_Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[Employee] WITH CHECK
ADD CONSTRAINT [IFManagerHasEmployees]
FOREIGN KEY([Manager_Id]) REFERENCES [dbo].[Employee] ([Emp_Id])
GO
ALTER TABLE [dbo].[Employee] CHECK CONSTRAINT [IFManagerHasEmployees]
GO
ALTER TABLE [dbo].[Employee] WITH CHECK
ADD CONSTRAINT [IFProjectHasEmployees]
FOREIGN KEY([Project_Id]) REFERENCES [dbo].[Project] ([Project_Code])
GO
ALTER TABLE [dbo].[Employee] CHECK CONSTRAINT [IFProjectHasEmployees]
GO
CREATE TABLE [dbo].[Bands]
(
[ThtrBandID] [char](2) NOT NULL,
[ThtrBandIssuerID] [char](1) NOT NULL,
[Description] [varchar](30) NOT NULL,
[AuditTime] [DateTime] NULL,
[Priority] [tinyint] NOT NULL,
[ConcurrencyToken] [timestamp] NOT NULL,
[TheatreBandsIdentity] [int] IDENTITY(1,1) NOT NULL,
CONSTRAINT [XPKBands] PRIMARY KEY CLUSTERED
(
[TheatreBandsIdentity] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY],
CONSTRAINT [XAK1Bands] UNIQUE NONCLUSTERED
(
[ThtrBandIssuerID] ASC,
[ThtrBandID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY],
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Items]
(
[SvcClass] [char](1) NOT NULL,
[ProgramID] INT NOT NULL,
[MBACNo] [smallint] NOT NULL,
[EffDate] [smalldatetime] NOT NULL,
[AuditTime] [DateTime] NULL,
[NatThtrBandIssuerID] [char](1) NULL,
[PatClass] [char](2) NULL,
[NatThtrBandID] [char](2) NULL,
[AHSAItemIdentity] [int] IDENTITY(1,1) NOT NULL,
CONSTRAINT [XPKAHSAItems] PRIMARY KEY CLUSTERED
(
[AHSAItemIdentity] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90)
ON [PRIMARY],
) ON [PRIMARY]
ALTER TABLE [dbo].[Items] WITH CHECK
ADD CONSTRAINT [IFTheatreBanding]
FOREIGN KEY([NatThtrBandIssuerID], [NatThtrBandID])
REFERENCES [dbo].[Bands] ([ThtrBandIssuerID], [ThtrBandID])
GO
My attempted SQL is sort of working ..
Returns:
SELECT * from dbo.Employee A JOIN dbo.Employee B ON A.Emp_Id = B.Manager_Id
SELECT * from dbo.Project A JOIN dbo.Employee B ON A.Project_Code = B.Project_Id
SELECT * from dbo.Bands A JOIN dbo.Items B ON A.ThtrBandID, ThtrBandIssuerID = B.NatThtrBandIssuerID, NatThtrBandID
This last one isn't correct ... and should be:
SELECT * from dbo.Bands A JOIN dbo.Items B ON A.[ThtrBandID] = B.[NatThtrBandID] AND A.[ThtrBandIssuerID] = B.[NatThtrBandIssuerID]

SQL Server aggregation with several joins

I'm trying to join data from 3 tables in SQL Servre and display in result:
Alias of an entity
if the entity is virtual
the last date (if known)
the value (if known)
I tried this :
select
sr.alias, c.virtual, max(d.date) date
from
App_references sr
join
Sensor c on (c.id_capteur = sr.id_capteur)
left join
Sensor_data d on (c.id_capteur = d.id_capteur)
group by
d.id_capteur, sr.alias, c.virtual
order by
sr.alias
Here is the database scheme:
CREATE TABLE [dbo].[App_reference]
(
[id_ref] [int] IDENTITY(1,1) NOT NULL,
[alias] [varchar](60) NOT NULL,
[id_capteur] [int] NOT NULL,
CONSTRAINT [PK_App_reference] PRIMARY KEY CLUSTERED
(
[id_ref] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[Sensor]
(
[id_capteur] [int] IDENTITY(1,1) NOT NULL,
[name] [varchar](50) NOT NULL,
[virtual] [tinyint] NULL,
[unite] [varchar](5) NULL,
[id_type] [int] NOT NULL,
CONSTRAINT [PK_Sensor] PRIMARY KEY CLUSTERED
(
[id_capteur] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[Sensor_data]
(
[id_entry] [int] IDENTITY(1,1) NOT NULL,
[id_capteur] [int] NOT NULL,
[value] [xml] NOT NULL,
[date] [datetime] NOT NULL,
CONSTRAINT [PK_Sensor_data] PRIMARY KEY CLUSTERED
(
[id_entry] ASC,
[id_capteur] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
Supposing each columns like "id_%" are linked by foreign key.
The request on top pass well, I got value :
alias virtual date
Place 1 (Physique) 0 2017-04-27 14:58:42.423
Place 2 1 NULL
Place 3 1 NULL
But I tried to select the value too by doing this :
select
sr.alias, c.virtual, max(d.date) date, d.value
from
Citopia_test.dbo.Smartparking_reference sr
join
Citopia_test.dbo.Sensor c on (c.id_capteur = sr.id_capteur)
left join
Citopia_test.dbo.Sensor_data d on (c.id_capteur = d.id_capteur)
group by
d.id_capteur, sr.alias, c.virtual
order by
sr.alias
And I got this error :
Column 'Sensor_data.value' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
So I tried several things like adding column in the group by but nothing changes.
You probably want the value from the record with max date. Use ROW_NUMBER to get those records.
select alias, virtual, date, value
from
(
select
sr.alias, c.virtual, d.date, d.value,
row_number() over (partition by sr.alias order by d.date desc) as rn
from Citopia_test.dbo.Smartparking_reference sr
join Citopia_test.dbo.Sensor c on (c.id_capteur = sr.id_capteur)
left join Citopia_test.dbo.Sensor_data d on (c.id_capteur = d.id_capteur)
) numbered
where rn = 1
order by sr.alias;
This gets you one row per sr.alias. If you want one row per sr.alias + c.virtual then change the partition by clause accordingly.

What is the optimal select according to you?

What is the optimal select according to you?
select #MailTo=ISNULL((select data from filedata where descid=3104 and DataId=evt04) ,'')
from event_21
where evtid=#nFileId
or
select #MailTo=ISNULL(data ,'')
from event_21
innerjoin filedata on event_21.evt04=filedata.dataid
where descid=3104
and evtid=#nFileId
Obviously "join" is faster than "inline select query". I have tested with 1000 rows. You can also test. here is the sample test code.
CREATE TABLE [dbo].[tableA](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](100) NOT NULL,
CONSTRAINT [PK_tableA] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[tableB](
[RowId] [int] IDENTITY(1,1) NOT NULL,
[Id] [int] NOT NULL,
[Designation] [nvarchar](100) NULL,
CONSTRAINT [PK_tableB] PRIMARY KEY CLUSTERED
(
[RowId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
Declare #Min Int = 1
,#Max Int = 1000
While (#Min <= #Max)
Begin
Insert Into tableA(Name)
Select 'Name would be the name of - ' + Cast(#Min As Nvarchar(10))
Insert Into tableB(Id,Designation)
Select #Min
,'Desig could be the name of - Name' + Cast(#Min As Nvarchar(10))
Select #Min = #Min + 1
End
First look # inline select query
-- inline query
Select a.Id
,a.Name
,(Select Designation From tableB As b Where b.Id = a.Id) As Designation
From tableA As a With (Nolock)
output:
Execution Plan:
now the Join query :-
---- join
Select a.Id
,a.Name
,b.Designation
From tableA As a With (Nolock)
Join tableB As b On a.Id = b.Id
execution plan for join query :-
you can see the clear difference.

Figure Out Which OrderIDs are 0$ Payment Totals

I am in need to some help writing a SQL 2012 query that will help me find and mark orderID's that are a $0.00 payments due to reversal(s)
So far I have:
Select Distinct a.orderID, a.orderPaid,
(Select SUM((c1.linePrice + c1.lineShippingCost + c1.lineTaxCost + c1.lineOptionCost) * c1.lineQuantity)
From vwSelectOrderLineItems c1 Where c1.orderID = a.orderID) As OrderAmount,
(Select SUM(b1.payAmount) FROM vwSelectOrderPayments b1 Where b1.orderID = a.orderID) as Payment,
1 As IsReversal
From vwSelectOrders a
Left Outer Join vwSelectOrderPayments b On b.orderID = a.orderID
Where b.payValid = 1 AND a.orderPaid = 0
Which is returning me some $0 payments on some orders. When I query that payment table with the orderID of these records, I can see that 2 payments were posted... 1 the original payment, 2 the reversal.
How Can I flag the Orders that are $0 payments?
Oders
CREATE TABLE [dbo].[TblOrders](
[orderID] [bigint] IDENTITY(1000,1) NOT NULL,
[orderPaid] [bit] NOT NULL,
[orderPaidOn] [datetime] NULL
CONSTRAINT [PK_TblOrders] PRIMARY KEY CLUSTERED
(
[orderID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 50) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[TblOrders] ADD CONSTRAINT [DF__TblOrders__order__1975C517] DEFAULT ((0)) FOR [orderPaid]
Order Line Items
CREATE TABLE [dbo].[TblOrderLineItems](
[lineID] [bigint] IDENTITY(1,1) NOT NULL,
[orderID] [bigint] NOT NULL,
[lineQuantity] [int] NOT NULL,
[linePrice] [money] NOT NULL,
[lineShippingCost] [money] NOT NULL,
[lineTaxCost] [money] NOT NULL,
[lineOptionCost] [money] NOT NULL,
CONSTRAINT [PK_TblOrderLineItems] PRIMARY KEY CLUSTERED
(
[lineID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 50) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[TblOrderLineItems] ADD CONSTRAINT [DF_TblOrderLineItems_lineShippingCost] DEFAULT ((0)) FOR [lineShippingCost]
GO
ALTER TABLE [dbo].[TblOrderLineItems] ADD CONSTRAINT [DF_TblOrderLineItems_lineTaxCost] DEFAULT ((0)) FOR [lineTaxCost]
GO
ALTER TABLE [dbo].[TblOrderLineItems] ADD CONSTRAINT [DF_TblOrderLineItems_lineOptionCost] DEFAULT ((0)) FOR [lineOptionCost]
GO
Order Payments
CREATE TABLE [dbo].[TblOrderPayments](
[paymentID] [bigint] IDENTITY(1,1) NOT NULL,
[orderID] [bigint] NOT NULL,
[payAmount] [money] NOT NULL,
[payPosted] [datetime] NOT NULL,
[payValid] [bit] NOT NULL,
CONSTRAINT [PK_TblOrderPayments] PRIMARY KEY CLUSTERED
(
[paymentID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 50) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[TblOrderPayments] ADD CONSTRAINT [DF_TblOrderPayments_payValid] DEFAULT ((0)) FOR [payValid]
GO
Views
CREATE VIEW [dbo].[vwSelectOrderLineItems] AS
SELECT linePrice, lineShippingCost, lineTaxCost, lineOptionCost, lineQuantity
FROM [dbo].[TblOrderLineItems]
CREATE VIEW [dbo].[vwSelectOrderPayments] AS
SELECT paymentID, orderID, payAmount, payValid
FROM dbo.TblOrderPayments
CREATE VIEW [dbo].[vwSelectOrders] AS
SELECT orderID , orderPaid
FROM dbo.TblOrders
Note
I cannot change the table structure
SELECT distinct a.orderid,
a.orderPaid,
c.OrderAmount
d.Payment
From vwSelectOrders AS a
INNER JOIN ( Select SUM((linePrice + lineShippingCost + lineTaxCost + lineOptionCost) * lineQuantity) As orderAmount,OrderID
From vwSelectOrderLineItems group by orderid) AS C on c.orderID = a.orderID
INNER JOIN (Select SUM(payAmount) as Payment,orderID FROM vwSelectOrderPayments WHERE isnull(SUM(PayAmount),0) > 0 GROUP BY OrderID) AS d ON d.orderID = a.orderID
Left Outer Join vwSelectOrderPayments b On b.orderID = a.orderID
Where b.payValid = 1 AND a.orderPaid = 0 AND
This is a better query as you do not have to us a correlated subquery. Correlated queries are when a subquery references an outerquery row. This isn't optimal because every row the outerquery runs the correlated subquery will execute. Once you give us table definitions we can probably fix the overall data return of your query.