How to select min datediff value on a record - sql-server

I've got a database of contacts that have registered to attend a range of events. The database also contains a table of address information. Frequently, individual contacts have multiple address records.
I need a query that returns an individual's event booking, along with the postcode from their most recent address record (relative to the date of the event).
I'm trying to use min(DATEDIFF) in the query below, but although it's correctly calculating the date difference between the event booking and the address record creation, the query's still returning duplicate results where an individual has more than one address record.
Appreciate if anyone can please advise where I'm going wrong in the query below, or advise on a better way to obtain the result:
SELECT ep.EVENTPLACENO, ad.POSTCODE, min(DATEDIFF(dd,ep.CREATIONDATE,ad.CREATIONDATE)) as datediff
FROM EVENTPLACE as ep
LEFT OUTER JOIN EVENTMODULE as em ON em.EVENTMODULENO=ep.EVENTMODULENO
LEFT OUTER JOIN ADDRESS as ad ON ad.CONTACTNO=ep.CONTACTNO
WHERE em.EVENTMODULENO = '1111111-2222222-3333333-4444444'
GROUP BY ep.EVENTPLACENO, ad.POSTCODE

SELECT ep.EVENTPLACENO, ad.POSTCODE, min(ad.CREATIONDATE) as datediff
FROM EVENTPLACE as ep
LEFT OUTER JOIN EVENTMODULE as em ON em.EVENTMODULENO=ep.EVENTMODULENO
OUTER APPLY (SELECT TOP 1 * FROM ADDRESS ad2 WHERE ad2.CONTACTNO=ep.CONTACTNO ORDER BY DATEDIFF(dd,ep.CREATIONDATE,ad2.CREATIONDATE)) AD
WHERE em.EVENTMODULENO = '1111111-2222222-3333333-4444444'
GROUP BY ep.EVENTPLACENO, ad.POSTCODE
you can use OUTER APPLY to LEFT JOIN to the TOP 1 of a sub query - the sub query then exists for the LEFT row that you are joining to the sub query - where the sub query is a TOP 1, it will join 1 to 1 (or 1 to null if no row)

Related

Trying to sum a joined subquery

For my sql class I am trying to write a query that sums a column in a sub query. The Sub query has a calculated value in it and I am trying to total that calculated value for particular zipcodes.
the query runs without errors but the output is null in the sum column
Tried running the sub query on its own and the value is calculated for the column properly
select c.CustomerState
,c.CustomerZip
,sum (b.TotalSales)as Sales
from [DBM460LearningTeam].[dbo].[TBLcustomer]as c
Left Join (select v.CustomerNumber
,sum (v.QuantitySold * i.ItemPrice) as TotalSales
from TBLinvoice as v
inner join TBLitem as i
on v.ItemNumber = right(i.ItemNumber,3)
group by v.CustomerNumber) as b
on c.CustomerNumber = b.CustomerNumber
group by c.CustomerZip , c.CustomerState;
I want to sum the total sales by zipcode so i expect to see column for zipcode and column for state and column for sales and thats what I get but the sales column is Null all the way down.
Your CustomerNumbers aren't lining up on your join on. I would verify that that part if you say you have a value for TotalSales when you just run the subquery. I bet if you changed that left join to an inner join you would get nothing. So you are getting all values from TBLCustomer but nothing matches on customernumber when you do the left join.

How to get column value of join query in SSRS?

I have select join query for generating report in SSRS. Query is working fine in SQL Server but as I add same query as dataset in SSRS and try to get rows count using CountRows() function it always return 0 (Zero). I'm not getting where my query is going wrong.
SQL Query
SELECT PR.NAME
FROm innovator.PROJECT PR
INNER JOIN innovator.PROJECT_RISK LPR ON LPR.SOURCE_ID = Pr.ID
INNER JOIN innovator.RISK_MANAGEMENT LR ON LR.id = LPR.RELATED_ID
Inner join innovator.PROGRAM_PROJECT P ON PR.ID = P.RELATED_ID
Inner Join innovator.PROGRAM PP ON P.SOURCE_ID = PP.ID
WHERE pp.ID = #Id
Fetching total count using CountRows() for Textbox
=CountRows(Fields!NAME.Value, "DataSetRisk")
DataSetRisk is Dataset name and Name is column name of Project Table
Use the CountRows function. For example
=CountRows("MyDataset")
Example : =CountRows("DataSetRisk")
will give you the number of rows in MyDataSet.
Try something a little simpler: Count(Fields!NAME.Value) as a column. This assumes, of course, that field name actually is populated. If the column is in separate groups, it will provide a count for each group, otherwise it will count for the entire report.

Adding column to select statement brings in all historical data

Good evening all!
I'm running into a really odd issue that I'm having trouble understanding.
I have 3 tables (parts table, parts move history and a parts detail table).
What I'm trying to do is have the result set return lot#,part#,product description,quantity,part location, what's currently in inventory (versus full history) and who last moved the product.
Now, for the query. When I run the below query, I get a result set of 4,751 rows; which lines up perfectly with my expected results. However, when I try to add in the userid field, I then get a result set of 186,573. This large result set appears to pull in all historic data versus just matching the userid to the 4,751 rows I actually need.
From the Parts Table I need (prod_desc)
From the Parts Detail Table I need (lot,part#,lotquantity,prtlocation)
From the Parts Move History Table I need (move_date,user_id)
4,751 Query:
SELECT DISTINCT
inv.lot,
inv.part#,
prt.prod_desc,
inv.lotquantity,
inv.prtlocation,
MAX(mv.move_date)AS 'Move Date'
FROM invdet AS inv
LEFT JOIN movetable AS mv ON inv.part# = mv.part#
LEFT JOIN partmstr AS prt ON inv.part# = prt.part#
WHERE inv.lot IS NOT NULL
GROUP BY inv.lot,inv.part#,prt.prod_desc,inv.lotquantity,inv.prtlocation
ORDER BY inv.prtlocation
186,573 Query:
SELECT DISTINCT
inv.lot,
inv.part#,
prt.prod_desc,
inv.lotquantity,
inv.prtlocation,
MAX(mv.move_date)AS 'Move Date'
mv.user_id
FROM invdet AS inv
LEFT JOIN movetable AS mv ON inv.part# = mv.part#
LEFT JOIN partmstr AS prt ON inv.part# = prt.part#
WHERE inv.lot IS NOT NULL
GROUP BY inv.lot,inv.part#,prt.prod_desc,inv.lotquantity,inv.prtlocation,mv.user_id
ORDER BY inv.prtlocation
If I don't use the MAX function, I do not get current inventory and instead get all results in the table, which I do not need. I'm still learning and my GROUP BY's leave a lot to be desired as I'm still wrapping my head around it (open to suggestions!). I'm sure there's a subquery I can throw in here somewhere, but I'm still figuring those out as well. Any help is greatly appreciated!
I think the problem is that when you insert mv.user_id from table movetable you get all part's movements and not only the last one with date max(mv.move_date).
One way is to remove the left join to movetable and use maybe a cross apply like
SELECT inv.lot,inv.part,prt.prod_desc,inv.lotquantity,inv.prtlocation,x.move_date,x.user_id
FROM invdet AS inv
CROSS APPLY(SELECT TOP 1
mv.user_id,mv.move_date
FROM movetable mv
WHERE inv.part=mv.part
ORDER BY mv.move_date DESC) AS x
LEFT JOIN partmstr AS prt ON inv.part=prt.part
WHERE inv.lot IS NOT NULL
ORDER BY inv.prtlocation
I've not tested it but should be fine, maybe a bit slow because cross apply executes one subquery per each row in inv table. If it is too slow, you can user ROWNUMBER to create a table composed of only the last movements and then use it in the LEFT JOIN, as follows
SELECT inv.lot,inv.part,prt.prod_desc,inv.lotquantity,inv.prtlocation,y.move_date,y.user_id
FROM invdet AS inv
LEFT JOIN(SELECT x.user_id,x.move_date,x.part
FROM (SELECT mv.user_id,mv.move_date,mv.part,rn=ROWNUMBER() OVER(PARTITION BY mv.part ORDER BY mv.move_date DESC)
FROM movetable mv) AS x
WHERE x.rn=1) AS y ON y.part=inv.part
LEFT JOIN partmstr AS prt ON inv.part=prt.part
WHERE inv.lot IS NOT NULL
ORDER BY inv.prtlocation
Hope it helps.

Grouping data based on expression using CountDistinct aggregate function

I am newbie to Stack overflow and also SQL server reporting services. So please excuse me for the format of the question.
So here is the situation:
I am developing a SSRS report which needs to be grouped by an Count of Distinct product names as shown below.
I created a text box called ProdCount with an expression
COUNTDISTNCT(Fields!Product.value,"DataSet1")
which gives me the count 63 within the scope of DataSet1.
Now i need to group the data by taking product names where the above formula is >1 .
=IIF(ProdCount>1,Fields!Product.value,Nothing)
My Problem:
I tried to call the ProdCount from the calculated field since i
cant use the aggregate functions in Calculated Fields and use
the second expression by using
= ReportItems!ProdCount.value
which gives me an error FieldValue Denying ReportItems
I tried to combine the above two expressions by creating a calculated field by
IIF(CountDistinct(Fields!Product.Value,"DataSet1")>1,Fields!Product.Value,Nothing)
which gives me an error Calculated fields cannot have expressions
I tried to use Report Variables in the same way as above(1) which was not working either.
I also tried to use CROSS JOIN in the query
Select Count(Distinct(Product Name)
from Query1
Cross join
My Main Query which give me the data
which is taking more time to execute.
So Can anyone help me with solution where i can group the data by combining the above two expressions.
Please excuse me for the format. I was confused with framing question. I accept all your edits , so that i can learn in future.
Here is my code:
SELECT * FROM
--Query1 which counts the number of distinct products)
(SELECT DISTINCT COUNT(gproduct.ProductName) AS ProdCount
FROM Table1
LEFT JOIN Table4
ON Table1.column=Table1.column
LEFT JOIN Table2
ON Table3.Column = TTable1.Column
LEFT JOIN
(
SELECT Distinct Table6.Name AS ProductName,Table9.ColumnId
FROM Table6
INNER JOIN Table7
ON Table6.Column=Table7.Column
INNER JOIN Table8
ON Table7.Column=Table8.Column
INNER JOIN Table9
ON Table9.Column=Table8.Column
)gproduct
ON Table1.ColumnId=gproduct.ColumnId
GROUP BY gproduct.ColumnId,
)qProduct
CROSS JOIN
--My main Query which get data from different table including Product name
(SELECT
Upper(CASE WHEN (CASE WHEN Table4.Column =1 THEN 'Yes' ELSE 'NO' END)='YES'
THEN gab.ProductName
ELSE
Table2.productName
END) AS Product,
FROM Table1 AS ec
LEFT JOIN Table2 AS ep
ON --
LEFT JOIN Table3 AS ebrd
ON --
Left JOIN Table4 AS etpc
ON --
LEFT JOIN Table5 AS gst
ON --
LEFT JOIN
(
SELECT Distinct Table6.Name AS ProductName,Table9.ColumnId
FROM Table6
INNER JOIN Table7
ON Table6.Column=Table7.Column
INNER JOIN Table8
ON Table7.Column=Table8.Column
INNER JOIN Table9
ON Table9.Column=Table8.Column
) gab
ON Table1.ColumnId=gab.ColumnId
)QMain
Personally I would try to solve the problem in query itself instead of SSRS report. According the data you provided it would be something like:
SELECT
ProductName,
count(distinct Product)
from
YourTable
group by
ProductName
having count(distinct product) > 1
Later on creating SSRS report should be quite easy.

MSSQL - Join tables and return user based on value in another table column

probably a badly worded question so apologies.
I have 3 tables that I want to join together.
I have created an SQLFiddle here
What I am wanting, is to compare the MAXLINEDISCOUNT from the linkloads table to the allowed discounts in the price_escalation_bands table.
so in the data, the maxlinediscount of 40 must match the next highest discount in the price_escalation_bands table where the customer_band is the same.
so I want the result to match row 1, where it is bronze and discount is 45. should my MAXLINEDISCOUNT be greater than 45, then go to the next highest which could be 50 in this case.
when it matches, return the fk_salesman_userid field and match this to the username in the users table.
Obviously, all this data is dynamic so needs to look at next highest...
Currently, it is returning as blank so dont think my syntax is quite correct.
my query is:
select price_authorized,load_number,maxlinediscount,customer_band,[price_escalation_bands].fk_salesman_userid,Users.firstname firstname,totalcost,period,creditlimit,currentbalance,customername,totalcubes,treatedcubes,normalcubes,pricingissue from #linkloads
left outer JOIN [price_escalation_bands] on [price_escalation_bands].band=#linkloads.customer_band
AND price_escalation_bands.discount = (
SELECT top 1 [price_escalation_bands].[discount]
FROM [price_escalation_bands]
WHERE [price_escalation_bands].band=#linkloads.customer_band
AND [price_escalation_bands].[discount]<=#linkloads.maxlinediscount
ORDER BY [price_escalation_bands].[discount]
)
left outer join Users
on Users.userid=[price_escalation_bands].fk_salesman_userid
Help, appreciated as always.
This lists all price_escalation_bands entries over the matching limit in linkloads:
select u.username
, peb.band
, peb.discount
, ll.maxlinediscount
from price_escalation_bands peb
join Users u
on peb.fk_salesman_userid = u.UserID
join linkloads ll
on ll.customer_band = peb.band
where ll.maxlinediscount < peb.discount
Your SQL Fiddle example with this query.

Resources