A solution for a join to get all the data that is not in the main query based on a field from the main query - sql

So I have the below case in crystal reports
Main Report which has a query that shows the batch details of an invoice
Sub-report which shows the details of the batches included in the main report but are not included in that document. So for example
Invoice A has 10 items all with the same batch (this will show in the main report)
Invoice B, C, an D has 3 more items in the same batch (so total 13 items for that batch in 4 different documents) and the 3 items that are not in document A is what appears in the sub-report.
Now it's easy to achieve that in Crystal Reports because you can link sub-reports with fields to filter directly without linking the queries, however since CR is not a database engine the filtration is super slow and to solve that I need a solution in an SQL query:
I tried converting it to UNION ALL so it's
Main Report
Union ALL
Sub Report
The problem is I am unable to replicate the sub-report case since the grouping needs to be by Document then Batch and the 3 items from the sub-report are not on the same document so they are not grouped by the same dimension now and that ruins the report.
I know it's not logical but after trying all the solutions that came to my mind I thought maybe someone more experienced would have a different opinion, basically for every invoice in the main report I need to show all items that are not in that specific invoice so right now I have no links because the Item is not the same, the document is not the same, and only the batch is the same but that's a many to many link.
EDIT: For simplicity let's say this is the main query
SELECT
T0.DocumentNumber,
T2.ItemCode,
T2.ItemName,
T3.BatchNumber,
T3.Quantity
FROM DocHeader T0
JOIN DocRows T1 ON T0.DocumentEntry = T1.DocumentEntry
JOIN ItemMaster T2 ON T1.ItemCode = T2.ItemCode
JOIN BatchTransaction T3 ON T1.Document Entry = T3.DocumentEntry and
T3.DocumentType = T1.DocumentType and T3.DocumentLine = T1.DocumentLine
The report is grouped by Document Number, so what i need is the same query but for every other document number that is not in the main query joined on the main query. The 2 problems are 1. They can leave the document number parameter blank and select all the documents in the table so this process needs to happen for each document seperately. 2. the document number in the sub query will never be the same so the grouping is an issue because the report needs to be grouped on the main query document number.

It would help if you wrote out your main query and some of the secondary queries you've tried, but assuming I understand your issue correctly, you should be able to just create an additional JOIN on the Batches table. This will have your SQL query list off ALL the Item rows for the Batch, then you can try to use conditional formatting and/or grouping in Crystal to to show/hide the rows as needed.
Alternatively, using the query described above, you may be able to use the linked Invoice Numbers you're now getting from your main report query to drive your Sub-Report, as opposed to going by the Batch # -- this may result in better performance.
EDIT: Based on your comment and update, I think the right approach here is to create a Stored Procedure. Doing a single query is probably not going to work, I took a crack at it and it's not worth the hassle.
Using a Stored Procedure you can create a table variable in memory, add the main invoice records to the table, then add the records for the secondary Invoices linked by the Batch number. Use some kind of column/flag in your table that indicates whether it's a 'Main Invoice' record or not, and use this flag to drive the Crystal display logic for how you want to show the main vs secondary/linked invoices.
It's doable!

Related

SQL Database "Operation must use an updateable query" Workaround

So my basic goal is to create a database for a shopsystem, which is my task to do for my IT course. I tried to create a UPDATE-Query, that collects all the Sale Positions ("tblPosition.PositionAnzahl") ordered with a SELECT-Query and groups it by the products ordered, to have an overview about how often each product has been sold.
I want to do this to keep track of how many items are still left in the inventory.
The Query was supposed to update 1 field ("tblArtikel.ArtikelVerkauft") in my table "tblArtikel", in which all my articles and their information is stored.
However, i just found out that you cannot run UPDATE-Queries, that use SELECT-Query data, as i get a error, that says "Operation must use an updateable query".
This is the code i used for the query:
UPDATE tblArtikel as a JOIN
(SELECT p.PositionArtikelID, Sum(p.PositionAnzahl) AS SumOfPositionAnzahl
FROM tblPositionen as p
GROUP BY p.PositionArtikelID
) p
ON a.ArtikelID = p.PositionArtikelID
SET ArtikelVerkauft = p.SumOfPositionAnzahl;
Is there another way to keep track of all the Items left in my inventory, apart from doing what i did?
Here are screenshots of the 2 tables (the depending fields are circled red):
tblPositionen with field PositionAnzahl
tblArtikel with field ArtikelVerkauft
I have not worked with SQL before and only learned about it during 45 min, so ther emight be an easy way for this, but i would still appreciate every answer from you guys.

Merge two CSV and collate data

I have two CSV files, the first like so:
Book1:
ID,TITLE,SUBJECT
0001,BLAH,OIL
0002,BLAH,HAMSTER
0003,BLAH,HAMSTER
0004,BLAH,PLANETS
0005,BLAH,JELLO
0006,BLAH,OIL
0007,BLAH,HAMSTER
0008,BLAH,JELLO
0009,BLAH,JELLO
0010,BLAH,HAMSTER
0011,BLAH,OIL
0012,BLAH,OIL
0013,BLAH,OIL
0014,BLAH,JELLO
0015,BLAH,JELLO
0016,BLAH,HAMSTER
0017,BLAH,PLANETS
0018,BLAH,PLANETS
0019,BLAH,HAMSTER
0020,BLAH,HAMSTER
And then a second CSV with items associated with the first list, with ID being the common attribute between the two.
Book2:
ID,ITEM
0001,PURSE
0001,STEAM
0001,SEASHELL
0002,TRUMPET
0002,TRAMPOLINE
0003,PURSE
0003,DOLPHIN
0003,ENVELOPE
0004,SEASHELL
0004,SERPENT
0004,TRUMPET
0005,CAR
0005,NOODLE
0006,CANNONBALL
0006,NOODLE
0006,ORANGE
0006,SEASHELL
0007,CREAM
0007,CANNONBALL
0007,GUM
0008,SERPENT
0008,NOODLE
0008,CAR
0009,CANNONBALL
0009,SERPENT
0009,GRAPE
0010,SERPENT
0010,CAR
0010,TAPE
0011,CANNONBALL
0011,GRAPE
0012,ORANGE
0012,GUM
0012,SEASHELL
0013,NOODLE
0013,CAR
0014,STICK
0014,ORANGE
0015,GUN
0015,GRAPE
0015,STICK
0016,BASEBALL
0016,SEASHELL
0017,CANNONBALL
0017,ORANGE
0017,TRUMPET
0018,GUM
0018,STICK
0018,GRAPE
0018,CAR
0019,CANNONBALL
0019,TRUMPET
0019,ORANGE
0020,TRUMPET
0020,CHERRY
0020,ORANGE
0020,GUM
The real datasets are millions of records, so I'm sorry in advance for my simple example.
The problem I need to solve is getting the data merged and collated in a way where I can see which item groupings most commonly appear together on the same ID. (e.g. GRAPE,GUM,SEASHELL appear together 340 times, ORANGE and STICK 89 times, etc...)
Then I need to see if there is any change/deviation to the general results in common appearance when grouped by SUBJECT.
Tools I'm familiar with are Excel and SQL, but I also have PowerBI and Alteryx at my disposal.
Full disclosure: Not homework, or work, but a volunteer project, thus my unfamiliarity with this kind of data manipulation.
Thanks in advance.
An Alteryx solution:
Drag the two .csv files onto your canvas (seen as book1.csv and book2.csv in my picture; Alteryx will create "Input" tools for you.
Drag a "Join" tool on and connect the two .csv files to its inputs; select "ID" as the join field; unselect the "Right_ID" as output since it's merely a duplicate of "ID"
Drag a "Summary" tool on and connect the Join tool's output to the Summary tool's input; select all three of the outputs and add as a "group by"... then add the ID column with a "count"
Drag a browse tool on and connect the summary's output to the browse tool's input.
run the workflow
After all that, click on the browse tool and you should see what is seen in my screenshot: (which is showing just the first ten rows of output):
+1 for taking on a volunteer project - I think anyone who knows data can have a big impact in support of their favourite group or cause.
I would just pull the 2 files into Power BI as 2 separate tables (Get Data / From File). Create a relationship between the 2 tables based on ID (it might get auto-generated). It should be one to many.
Then I would add a Calculated Column to the Book1 table to Concatenate the related ITEM values, eg.
Items =
CALCULATE (
CONCATENATEX (
DISTINCT ( 'Book2'[ITEM] ),
'Book2'[ITEM],
", ",
'Book2'[ITEM], ASC
)
)
Now you can use that Items field in visuals (e.g. a Table), along with Count of ID to get the frequency.
Adding Subject to a copy of the table (e.g. to the Columns well of a Matrix) will produce your grouped scenario, or you could add a Subject Slicer.
As you will be comparing subsets of varying size, I would change Count of ID to Show value as - % of grand total.
Little different solution using Alteryx.
With this dataset, there are very few repeating 3 or 4 item groups. You can do the two item affinity analysis and get a probability of 3 or 4 item groups, or you can count the 3 and 4 item groups individually. I believe what you want is the latter as your probability of getting grapes with oranges may be altered by whether you have bananas in the cart or not.
Anyway, I did not join in the subject until after finding all of my combinations. I found all the combinations by taking the Cartesian join of two, then three, then four of the original set. I then removed all duplicates by ensuring items were always in alphabetical order in each row. I then counted occurrences of each combination. More joins can be added in the same pattern to count groups of 5,6,7...
Once you have the counts of occurrences, then I would join back with the subjects and perform this analysis on each group and compare to the overall results.
I'm supposed to disclose that I work for Alteryx.
first of all if you are using windows
just navigate to the directory which contains the CSV and write the following command:
copy pattern newfileName.csv
#example
copy *.csv merged.csv
now you created one csv file, the file is too large now you can't process it once, depending on your programming language you can use appropriate way, for python you can use generators to process line by line, or pandas you can read chunk by chunk it will be easy.
I hope this help you.

SQL query / SQL Reporting Services

Been rattling my brain for a while and I could not get pass how to do the SQL query that will show the relationship/connections between my two tables.
I'm working on an IT equipment inventory program. I have two tables;
SELECT serial_number, model, ship_dat, status FROM items_list
SELECT item_serial, connected-to_serial FROM connections
All items like desktops, laptops, monitors, etc are on the items_list table. To track down the relationship/connections of the items, I created the connections table. IE, Monitor with serial_number=Screen#1 is connected to a Desktop with serial_number=Serial#1. It works ok with my Window Form application because I
used a datagridview control to list all devices simple SQL query.
However, when trying to show the relationship/connection on SQL Reports I've ran out of ideas how to do it. I'm aiming to get the report look like below or something along the lines. I just need to show the connections between the items.
Thank you
You should be able to do this with a table in SSRS if that is what you are using. The query you would need to drive the table of all related items would be:
SELECT item_serial, connected-to_serial, mainItem.*, connectedItem.*
FROM connections
INNER JOIN items_list mainItem ON connections.item_serial = items_list.serial_number
INNER JOIN items_list connectedItem ON connections.connected-to_serial = connectedItem.serial_number
You can of course tailor the SELECT statement to your needs, mainItem.* and connectedItem.* will not give you the most descriptive column names. Using column aliases (found under column_alias here) you can give a more descriptive name to each column.
From here you should be able to use a table and create a row group on the main item (either name or serial number) to get the type of look you are looking to achieve here. I believe the Report Wizard actually has most of the functionality you are looking for and should handle the bulk of this. You may have to move some of the cells around to get the look you are going for though.

MS Access report fails to total correctly

I have a report in MS Access 2010 that had been working fine for a while. I had to make updates to the report to allow the run-time selection of one or more 'reasons' that would be included on the report.
My initial process dynamically built them into the report filter at run-time, but my totals came out wrong. I then dynamically altered the QueryDef.SQL (adding the final two AND statements in the code below) that the report is based on, but they still came out wrong. I then discovered (did I mention that I'm not the one who originally wrote the report) that the total field is based on another query entirely.
Quick background before everyone questions the sanity: We're calculating an audit score. Each audit is checked on several questions, most of which receive a Yes/No (pass/fail) answer. Some questions may receive a 'Total Fail' which results in a zero score for the entire audit, not just for the particular question. The individual audit score is percentage right OR zero if there is a 'Total Fail'. The overall score on the report is the average of the individual audit scores.
So, with that background, I would hope that there is enough information to make sense of the queries.
This is the query (qryRptAtt) that the report is based on:
SELECT vwAttorneys.CurrentAttorneyName AS PayeeID, tblAuditAtt.AttAudit_ID,
vwAttorneys.CurrentAttorneyName AS Attorney_Name, tblAuditAtt.Loan,
tblAuditAtt_A.A_ID, tblAuditAtt_Q.Question, tblAuditAtt_A.Answer,
tblAuditAtt_A.Comment, tblAuditAtt.EndDate, tblAuditAtt.Status,
tblAuditAttLoans.State, tblAuditAtt.Reason
FROM tblAuditAttLoans RIGHT JOIN ((vwAttorneys INNER JOIN tblAuditAtt ON
vwAttorneys.PayeeID = tblAuditAtt.PayeeID) INNER JOIN (tblAuditAtt_Q
INNER JOIN tblAuditAtt_A ON tblAuditAtt_Q.A_ID = tblAuditAtt_A.A_ID) ON
tblAuditAtt.AttAudit_ID = tblAuditAtt_A.AttAudit_ID) ON
tblAuditAttLoans.LoanNumber = tblAuditAtt.Loan
WHERE (((tblAuditAtt_A.Answer)<>"NA")
And ((tblAuditAtt.EndDate) Between Forms!frmRptAtt!txtFrom And Forms!frmRptAtt!txtTo)
And ((tblAuditAtt.Status)="Submitted"))
AND tblAuditAtt.Reason in ('reason1', 'Reason 2', 'Reason 3', 'Reason 4', 'Reason 5')
AND tblAuditAtt.PayeeID = '<removed for privacy>'
ORDER BY vwAttorneys.Attorney_Name, tblAuditAttLoans.State, tblAuditAtt.Loan, tblAuditAtt_A.A_ID
(All the horrendous parenthesis come from Access building the query from the visual designer. Yes, there are some columns selected twice - I will clean that up if possible.)
This query is correctly giving me all the detail information I need on the report. In the report itself, the overall score field in the footer section of the report has Control Source set to =IIf([txtA_TF]=0,DAvg("[Score]","[qryRptAttAggregateAudits]"),0). This is the one that is giving me the wrong answer. qryRptAttAggregateAudits is as follows:
SELECT qryRptAtt.PayeeID, qryRptAtt.AttAudit_ID, qryRptAtt.Loan,
Sum(IIf(Answer="Yes",1,0)) AS Yes,
Sum(IIf(Answer="No",1,0)) AS [No],
Sum(IIf(Answer="DC",1,0)) AS DC,
Sum(IIf(Answer="TF",1,0)) AS TF,
IIf(DC>0,0,IIf(TF>0,0,Sum(IIf(Answer="Yes",1,0))/(Sum(IIf(Answer="Yes",1,0))+Sum(IIf(Answer="No",1,0))))) AS Score
FROM qryRptAtt
WHERE (((qryRptAtt.PayeeID)=[Forms]![frmRptAtt]![cmbAttorney]))
AND qryRptAtt.Reason in ('Reason1', 'Reason2', 'Reason3', 'Reason4', 'Reason5')
AND qryRptAtt.PayeeID = '<removed for privacy>'
GROUP BY qryRptAtt.PayeeID, qryRptAtt.AttAudit_ID, qryRptAtt.Loan
The report total query selects from the report detail query qryRptAtt. In both queries, Forms!frmRptAtt is open and has had the appropriate fields filled with valid data.
I've tried the total query with both (((qryRptAtt.PayeeID)=[Forms]![frmRptAtt]![cmbAttorney])) and AND qryRptAtt.PayeeID = '<removed for privacy>' in the WHERE clause, with only one and with only the other (They both resolve to the same criteria, so it's really just redundant code & will be cleaned up once I get the major issue resolved).
I've exported the report to Excel and manually calculated the score there, and the report is showing a total that is about 0.6% off.
If anyone was able to follow this, do you have any suggestions?
It turns out that there was an oddity in the report definition.
The 2nd query was being used to generate rows of data that were being totaled with DAvg() in the report. The DAvg() function worked on a query result before I made my changes, but didn't seem to want to work with the query after I made the changes.
I modified the 2nd query to build a temporary table, then modified the DAvg() call in the report to reference the table instead of the query, and that seems to have it working.

VBA, SQL, Queries

I have an access form with few controls on it, like start-date, end-date, move_type, mover_name etc, when user fills this field n clicks on query command button, a select query is run and it fetches records from various tables depending upon the criteria mentioned by the user.
Later the same records are exported to excel file and a report is generated for user.
Now I need to do more with this, my select query has a field "quoted-price", depending upon the price quoted the records need to be sorted out.
EX : if quoted_price < 500 then it is a "domestic apartment1", if quoted-price is >500 And <1500 it is "domestic Apartment1" etc.
Now I need to do more with this, my select query has a field "quoted-price", depending upon the price quoted the records need to be sorted out.
EX : if quoted_price < 500 then it is a "domestic apartment1", if quoted-price is >500 And <1500 it is "domestic Apartment1" etc. and when all the records generated through select query are searched on this criteria, the records need to be grouped accordingly. Later the count for individual category is multiplied by a unit value and total charge is calculated.
I tried building many queries to do this and tables to refer to value but of no use. Any help will be much appreciated.
are you looking to create a new field depending on the condition? That may be step one of what you are trying to do, If so that is pretty easy. See here: http://allenbrowne.com/casu-14.html