Mixed scenarios in MS Access - ms-access

This is my table [Property]:
Loanno Balance amount PropertyType
1001045 308731.770000 1
1001045 2007700.740000 2
1001045 3087318905.770 3
1001045 308731.770000 4
1001046 306589.67 1
1001046 456321.23 1
1001046 6932542.89 1
1001047 582563.56 1
1001047 965421.34 2
1001048 567894.34 1
1001048 567894.34 2
I have to get the property type for a [Loanno] having highest balance amount.
If there is a tie in the highest balance amount and if the Property type for the loannumber is different then for that Loan number I have to populate property type as '8'.
So my final Output should look like this:
Loanno PropertyType
1001045 3
1001046 1
1001047 2
1001048 8
Edit
This is what I tried, but I am getting duplicate records.
SELECT DISTINCT
LT.LOANNO,
IIF(COUNTS.MAX_BALANCE > 1, 8,LT.PROPERTY_TYPE) AS PROPERTY_TYPE1
FROM
PROPERTY LT
INNER JOIN
(
SELECT
DISTINCT_ROWS.LOANNO,
COUNT(DISTINCT_ROWS.MaxBalance) AS MAX_BALANCE
FROM
(
SELECT DISTINCT
L.LOANNO,
MaxBalance
FROM
PROPERTY AS L
INNER JOIN
(
SELECT
LOANNO,
MAX(BALANCE_AMOUNT) AS MaxBalance
FROM PROPERTY
GROUP BY LOANNO
) AS SUB
ON (L.LOANNO=SUB.LOANNO)
AND (L.BALANCE_AMOUNT=SUB.MaxBalance)
) AS DISTINCT_ROWS
GROUP BY DISTINCT_ROWS.LOANNO
) AS COUNTS
ON LT.LOANNO=COUNTS.LOANNO
GROUP BY LT.LOANNO, IIF(COUNTS.MAX_BALANCE > 1, 8, LT.PROPERTY_TYPE)

Your query requirements are challenging for Access SQL. A custom VBA function would allow you to use a simpler SELECT statement, but brings issues which may be unacceptable for you:
A UDF (user-defined function) can only be used in a query run within an Access session ... not when you use other code (.Net, Java, PHP, VBScript, etc) to connect to the db and run your query.
UDFs can be slow.
If you can use a UDF, this query using the GetPropertyType function (see below) returns what you asked for. Note I used tblProperties as the table name because Property is a reserved word. Also I assumed Long for the data type of Loanno, Currency for Balance_amount, and Long for Property_Type.
SELECT
sub.Loanno,
GetPropertyType(sub.Loanno,sub.MaxBalance) AS PropertyType
FROM
(
SELECT
Loanno,
Max(Balance_amount) AS MaxBalance
FROM tblProperties
GROUP BY Loanno
) AS sub
ORDER BY sub.Loanno;
This is the function, which I tested with Access 2007.
Public Function GetPropertyType(ByVal pLoanno As Long, _
ByVal pBalance_amount As Currency) As Long
Const cstrQdf As String = "qryLoanPropertyTypesCount"
Dim db As DAO.database
Dim qdf As DAO.QueryDef
Dim lngReturn As Long
Set db = CurrentDb
Set qdf = db.QueryDefs(cstrQdf)
qdf.Parameters("which_Loanno") = pLoanno
qdf.Parameters("which_Balance_amount") = pBalance_amount
If qdf.OpenRecordset()(0) > 1 Then
lngReturn = 8
Else
lngReturn = DLookup("Property_Type", "tblProperties", _
"Loanno=" & pLoanno & " AND Balance_amount=" & _
pBalance_amount)
End If
Set qdf = Nothing
Set db = Nothing
GetPropertyType = lngReturn
End Function
The function uses this saved parameter query, qryLoanPropertyTypesCount:
PARAMETERS which_Loanno Long, which_Balance_amount Currency;
SELECT Count(*) AS num_PropertyTypes
FROM
(
SELECT DISTINCT
p.Loanno,
p.Balance_amount,
p.Property_Type
FROM tblProperties AS p
WHERE
p.Loanno = [which_Loanno]
AND p.Balance_amount = [which_Balance_amount]
) AS sub;

Here's how I built up the query:
Step 1: Create a query to find the maximum balance for each [Loanno] and save that query as [Loanno_MaxBalance]:
SELECT
Loanno,
MAX([Balance amount]) AS MaxBalance
FROM [Property]
GROUP BY Loanno
Step 2a: Create a query to count the number of rows that have the maximum balance, using our saved query above to keep things simple:
SELECT
[Property].Loanno,
[Property].[Balance amount],
COUNT(*) AS RowCount
FROM
[Property]
INNER JOIN
[Loanno_MaxBalance]
ON Loanno_MaxBalance.Loanno=[Property].Loanno
AND Loanno_MaxBalance.MaxBalance=[Property].[Balance amount]
GROUP BY [Property].Loanno, [Property].[Balance amount]
Step 2b: That doesn't look too scary, so let's incorporate the SQL from Step 1 as a subquery:
SELECT
[Property].Loanno,
[Property].[Balance amount],
COUNT(*) AS RowCount
FROM
[Property]
INNER JOIN
(
SELECT
Loanno,
MAX([Balance amount]) AS MaxBalance
FROM [Property]
GROUP BY Loanno
) AS Loanno_MaxBalance
ON Loanno_MaxBalance.Loanno=[Property].Loanno
AND Loanno_MaxBalance.MaxBalance=[Property].[Balance amount]
GROUP BY [Property].Loanno, [Property].[Balance amount]
So now this query stands on its own, and we don't need to keep [Loanno_MaxBalance] as a separate saved query in Access.
We'll save the above query as [Loanno_MaxBalance_Count].
Step 3a: Now to derive the [PropertyType] values using the [Property] table and the [Loanno_MaxBalance_Count] query:
SELECT DISTINCT
[Property].Loanno,
IIf(Loanno_MaxBalance_Count.RowCount>1, 8, [Property].PropertyType) AS PropertyType
FROM
[Property]
INNER JOIN
[Loanno_MaxBalance_Count]
ON [Property].Loanno=Loanno_MaxBalance_Count.Loanno
AND [Property].[Balance amount]=Loanno_MaxBalance_Count.[Balance amount]
Step 3b: Gee, that's not too bad at all. Let's "go for it" and replace the [Loanno_MaxBalance_Count] query reference with its SQL code (from Step 2b) as a subquery:
SELECT DISTINCT
[Property].Loanno,
IIf(Loanno_MaxBalance_Count.RowCount>1, 8, [Property].PropertyType) AS PropertyType
FROM
[Property]
INNER JOIN
(
SELECT
[Property].Loanno,
[Property].[Balance amount],
COUNT(*) AS RowCount
FROM
[Property]
INNER JOIN
(
SELECT
Loanno,
MAX([Balance amount]) AS MaxBalance
FROM [Property]
GROUP BY Loanno
) AS Loanno_MaxBalance
ON Loanno_MaxBalance.Loanno=[Property].Loanno
AND Loanno_MaxBalance.MaxBalance=[Property].[Balance amount]
GROUP BY [Property].Loanno, [Property].[Balance amount]
) AS Loanno_MaxBalance_Count
ON [Property].Loanno=Loanno_MaxBalance_Count.Loanno
AND [Property].[Balance amount]=Loanno_MaxBalance_Count.[Balance amount]
That's it! One self-contained query with no need for saved Access query dependencies.

Related

Order a report builder report by the parameters entered

So I have an SSRS report with one parameter and got a request to order the report by the exact order that the parameter/order numbers entered. Is there any way to sort the report this way?
For example, the parameters/order numbers entered in order: 5, 10, 1, 3, 2
I need the report to come out in that exact order
Table:
Order Number
Customer
5
A
10
B
1
C
3
D
2
E
Below is the query too, but I don't think this is anything I could do in sql server anyway.
SELECT c.customer_name AS [Customer]
, oh.order_no AS [Pick Ticket Number]
FROM orders oh
INNER JOIN customer c ON oh.customer_id = c.customer_id
WHERE oh.order_no IN (#orderno)
GROUP BY c.customer_name, oh.order_no
If you are using a drop down list of order numbers for the user to choose from, then I don't you can do this easily as there is no way to know which order they were clicked in.
If the users are just typing into a multivalue parameter and pressing enter between each entry then you can do it like this...
Add new new parameter to your report (this can be hidden) call it something like 'pOrderSort` and set the Default Value expression to be
=JOIN(Parameters!orderno.Value, ",")
This will create a string, something like "5,10,1,3,2".
Now change your dataset query to this..
declare #Seq table(orderNum int, SortBy int IDENTITY(1,1))
INSERT INTO #Seq (orderNum)
SELECT value from string_split(#pOrderSort, ',')
SELECT c.customer_name AS [Customer]
, oh.order_no AS [Pick Ticket Number]
, s.SortBy
FROM orders oh
INNER JOIN customer c ON oh.customer_id = c.customer_id
INNER JOIN #Seq s ON oh.order_no = s.orderNum
GROUP BY c.customer_name, oh.order_no
ORDER BY s.SortBy
All we are doing here is splitting the passed in parameter into rows and assigning a sequence number in the SortBy column.
Now all we do is join to this table and order by the SortBy column. There is no need for the WHERE clause as we are joining only to the order number we need.
You can use the SortBy column in the report design to order the rows as required.
I had to do it without string_split() so below is the code to get around that, other than that I followed Alan's answer with creating a hidden parameter named #orderlist that is joined with the #orderno parameter
DECLARE #str varchar(max)
SET #str = #orderlist
DECLARE #separator varchar(max)
SET #separator = ','
DECLARE #Splited TABLE(id int IDENTITY(1,1), item decimal(19,0))
SET #str = REPLACE(#str, #separator, '''),(''')
SET #str = 'SELECT * FROM (VALUES(''' + #str + ''')) AS V(A)'
INSERT INTO #Splited
EXEC(#str)
SELECT c.customer_name AS [Customer]
, oh.order_no AS [Pick Ticket Number]
FROM oe_hdr oh
INNER JOIN customer c ON oh.customer_id = c.customer_id
INNER JOIN #Splited ot ON ot.item = oh.order_no
GROUP BY c.customer_name, op.pick_ticket_no, ot.id
ORDER BY ot.id ASC

Update Query with Static Value and Dynamic Value

I am trying to update two columns on a table, in MS Access using Microsoft 365. One value is static and one is based on a select query. However I continue to get Operation must use an updateable query error message. Below is my query:
UPDATE tblBuckets AS e
SET e.DiscountExclusion = "SpecialDisc", e.DrugSpecDisc = (
SELECT sd.[Discount Rate]
FROM tblDrugSpecDis AS sd
INNER JOIN tblClaims AS s ON sd.[Drug ID] = LEFT(s.ndc11code, sd.[Length of Drug ID])
WHERE sd.Indicator = 'N'
)
WHERE e.sourceclaimid IN (
SELECT s.sourceclaimid
FROM tblClaims AS s
INNER JOIN tblDrugSpecDis AS sd ON sd.[Drug ID] = LEFT(s.ndc11code, sd.[Length of Drug ID])
WHERE sd.Indicator = 'N'
)

MySQL select query on multiple table does not display the comm data

here is my current query and it access four tables. Everything else displays the correct data except for this part:
IF(tbl_shift.commission IS NULL,'0.00', (tbl_shift.commission*tbl_payment.subtotal)) AS comm,
this doesn't seem to access the data from the table.
Here is the full query:
SELECT tbl_payment.dateTime AS purchasedate, tbl_payment.invoiceNo AS invoice,
tbl_payment.subtotal AS total, tbl_payment.staffid AS employee,
tbl_users.fname AS firstname, tbl_users.lname AS lastname,
IF(tbl_shift.commission IS NULL,'0.00', (tbl_shift.commission*tbl_payment.subtotal)) AS comm,
(SELECT COUNT(1) AS qty FROM tbl_purchases
WHERE tbl_payment.invoiceNo=tbl_purchases.invoiceNo) AS qty
FROM `tbl_payment`
LEFT JOIN tbl_shift ON tbl_payment.staffid = tbl_shift.employeeId
AND tbl_payment.dateTime BETWEEN tbl_shift.startShift
AND tbl_shift.endShift
INNER JOIN tbl_users ON tbl_payment.staffid = tbl_users.id
WHERE tbl_payment.staffid = ".$staff."
AND dateTime BETWEEN '".$from."' AND '".$to."'
ORDER BY tbl_payment.dateTime DESC
if this succeeds
IF(tbl_shift.commission IS NULL,'0.00', (tbl_shift.commission*tbl_payment.subtotal)) AS comm,
Wouldn't it mean that you would have both string values and numbers in the same column if both are true for any rows?
Perhaps try this and see what happens:
IF(ISNULL(tbl_shift.commission)=1,0,(tbl_shift.commission*tbl_payment.subtotal)) AS comm,

SQL Query behavior

I'm bogged in trying to figure out why query a is returning different records than query b. Both queries have seemingly same purpose yet a is returning 500 and b 3500.
this is query a:
SELECT DISTINCT ODE.OrderBillToID
FROM APTIFY.dbo.vwVwOrderDetailsKGExtended ODE
WHERE ProductID IN (2022, 1393)
AND LTRIM(RTRIM(ODE.OrderStatus)) <> 'Cancelled'
AND LTRIM(RTRIM(ODE.OrderType)) <> 'Cancellation'
AND LTRIM(RTRIM(ODE.cancellationStatus)) <> 'FULLY CANCELLED'
UNION
SELECT DISTINCT ID
FROM APTIFY.dbo.vwPersons WHERE City = 'A'
UNION
SELECT DISTINCT RecordID
FROM APTIFY.dbo.vwTopicCodeLinks WHERE TopicCodeID = 16 AND Value = 'Yes, Please'
query b:
SELECT
APTIFY..vwPersons.ID
FROM
APTIFY..vwPersons
WHERE
( APTIFY..vwPersons.ID IN (
SELECT
vwMeetingRegistrants.ID
FROM
APTIFY.dbo.vwMeetings vwMeetings
INNER JOIN APTIFY.dbo.vwMeetingRegistrants vwMeetingRegistrants
ON vwMeetings.ID=vwMeetingRegistrants.ActualMeetingID WHERE
vwMeetings.ProductID = 2022
)
OR
APTIFY..vwPersons.ID IN (
SELECT
vwMeetingRegistrants.ID
FROM
APTIFY.dbo.vwMeetings vwMeetings
INNER JOIN APTIFY.dbo.vwMeetingRegistrants vwMeetingRegistrants
ON vwMeetings.ID=vwMeetingRegistrants.ActualMeetingID WHERE
vwMeetings.ProductID = 1393
)
OR
APTIFY..vwPersons.City = N'Albany' )
OR
((
APTIFY..vwPersons.ID IN (
SELECT
RecordID
FROM
APTIFY.dbo.vwTopicCodeLinks vwTopicCodeLinks
WHERE
vwTopicCodeLinks.TopicCodeID = 16
)
AND
APTIFY..vwPersons.ID IN (
SELECT
RecordID
FROM
APTIFY.dbo.vwTopicCodeLinks vwTopicCodeLinks
WHERE
vwTopicCodeLinks.Value = N'Yes, Please'
) )
)
vwMeetingsRegistrants from the b query are producing the same records as orderkgdetailsextended from query. I cannot see ANY difference in those queries - which perhaps shows my lack of understanding the query behaviour.
BIG Thanks for any points guys! :)
As it came out, incorrectly structured query is a result of badly configured application, Aptify.

Tracking report usage

Is there an easy way to track who is running a given report in SSRS 2005, and at what time they are running that report? We have about 80 reports in our SSRS implementation, and are trying to see if there's any that we can safely put out to pasture. If we could easily see somehow which reports aren't being used, that would help us. Any ideas?
There is some good advice and queries for generating reports on this in the following article.
For example, if you want to see the most used reports, you can do the following:
SELECT COUNT(Name) AS ExecutionCount,
Name,
SUM(TimeDataRetrieval) AS TimeDataRetrievalSum,
SUM(TimeProcessing) AS TimeProcessingSum,
SUM(TimeRendering) AS TimeRenderingSum,
SUM(ByteCount) AS ByteCountSum,
SUM([RowCount]) AS RowCountSum
FROM (SELECT TimeStart,
Catalog.Type,
Catalog.Name,
TimeDataRetrieval,
TimeProcessing,
TimeRendering,
ByteCount,
[RowCount]
FROM Catalog
INNER JOIN
ExecutionLog
ON Catalog.ItemID = ExecutionLog.ReportID
WHERE Type = 2
) AS RE
GROUP BY Name
ORDER BY COUNT(Name) DESC,
Name;
One thing to note is that by default the execution log will only keep 2 months worth of data. You can control this behaviour with the ExecutionLogDaysKept server property, see this technet article.
I know this question is so old it has whiskers, but the code below will list each report once with the last time it was run. I highly recommend you create a new folder called "obsolete reports" and move old reports there rather than delete them. That will remove the clutter but still keep them available in case the Accounting Department comes after you for that report they obviously need to run once every 3.26 years.
WITH RankedReports
AS
(SELECT ReportID,
TimeStart,
UserName,
RANK() OVER (PARTITION BY ReportID ORDER BY TimeStart DESC) AS iRank
FROM dbo.ExecutionLog t1
JOIN
dbo.Catalog t2
ON t1.ReportID = t2.ItemID
)
SELECT t2.Name AS ReportName,
t1.TimeStart,
t1.UserName,
t2.Path,
t1.ReportID
FROM RankedReports t1
JOIN
dbo.Catalog t2
ON t1.ReportID = t2.ItemID
WHERE t1.iRank = 1
ORDER BY t1.TimeStart;
i always found the report logs are a bit hard to use. Reporting services keeps a record of all its activity in a table in the reporting database called ExecutionLog
I have a couple of reports i use that query this table, so you can find out what reports are actually used, and who the heaviest users are
You can monitor the report usage using execution logs. Please check this http://technet.microsoft.com/en-us/library/aa964131(SQL.90).aspx
You can also run a query to find report usage. Check Maz's reply in this link http://www.sqlservercentral.com/Forums/Topic433562-150-1.aspx
cheers
This SQL will also give you the data source, user and the request type:
select row_number() over (order by LogEntryId) as Id, LogEntryId,
r.Name AS Report_Name, r.Path AS Report_Path, c2.Name AS Data_Source,
replace(c2.ConnectString,';Unicode=True','') as ConnectString,
SUBSTRING(r.Path, 2, LEN(r.Path) - LEN(r.Name) - 2) AS Folder_Path,
ex.UserName, ex.Format, ex.TimeProcessing, ex.TimeRendering, ex.[RowCount],
CAST (ex.TimeStart as date) AS TimeStart,
DATEPART (hour, ex.TimeStart) AS StartHour,
DATEPART (minute, ex.TimeStart) AS StartMinute,
case
when ex.RequestType = 0 then 'Interactive'
when ex.RequestType = 1 then 'Subscription'
when ex.RequestType = 2 then 'Refresh Cache'
else 'Unknown' end RequestType,
u.UserName as CreatedBy,
ex.Status
from ExecutionLogStorage ex (nolock) --exec log
join Catalog (nolock) r on ex.ReportID = r.ItemID and r.Type = 2 --report
join DataSource ds with (nolock) ON ds.ItemID = r.ItemID --report to connection link
join (select ItemID, Name, SUBSTRING(Content, CHARINDEX('<ConnectString>',Content) + 15, CHARINDEX('</ConnectString>',Content) - CHARINDEX('<ConnectString>',Content) - 15) AS ConnectString
from ( select ItemID, Name, CONVERT(NVARCHAR(MAX),CONVERT(XML,CONVERT(VARBINARY(MAX),Content))) As Content
from Catalog with (nolock) where Type = 5) x
) c2 ON ds.Link = c2.ItemID -- connection
left join Users u on u.UserID = r.CreatedByID
USE ReportServer
SELECT c.Name AS ItemName
, CASE c.Type
WHEN 1 THEN 'Folder'
WHEN 2 THEN 'Report'
WHEN 3 THEN 'Resource'
WHEN 4 THEN 'Linked Report'
WHEN 5 THEN 'Data Source'
ELSE CAST(c.Type AS VARCHAR(100))
END AS ItemType
, c.Path AS ItemPath
, ( SELECT TOP 1 TimeStart FROM dbo.ExecutionLog t1 WHERE t1.ReportID = c.ItemID ORDER BY TimeStart DESC ) AS LastRunDate
, ( SELECT TOP 1 UserName FROM dbo.ExecutionLog t1 WHERE t1.ReportID = c.ItemID ORDER BY TimeStart DESC ) AS LastUser
FROM Catalog AS c WITH (NOLOCK)
WHERE 1=1
--AND c.Type IN (1,2)
--uncomment if searching for reports and folders only