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