MS Access: Query to combine rows - sql

I have 3 tables:
Clients
User_Defined_Definitions
User_Defined_Data
The Clients table has basic information:
ClientID, Name, Address...
The User_Defined_Definitions has the title for the user def fields:
StartDate, SalesRep, Website...
Then the User_Defined_Data table contains the data to fill those fields for each client in the client table.
I've built a query which pulls all the data I need, but it pulls one row for each of the User_Defined_Data rows that exist for that client. What I would like to do is pull one row for each client, and append as many columns as needed to fill all the user defined fields into the one row.
ClientID Name Address Description Data
155555 Calvin 123 Fake St StartDate 10/10/2013
155555 Calvin 123 Fake St SalesRep Tom
155555 Calvin 123 Fake St Website http://www.fakesite.com
155556 Steve 456 Root Rd StartDate 8/5/2013
155557 Kathy 715 Main St StartDate 5/5/2010
155557 Kathy 715 Main St SalesRep Jessica
155557 Kathy 715 Main St Website http://www.fakesite2.com
155558 Jenny 345 Fake St StartDate 9/9/2012
155558 Jenny 345 Fake St Website http://www.fakesite3.com
The first three columns come from the Client table. The Description column comes from the User_Defined_Definitions table. And the Data comes from the User_Defined_Data table.
And I'd like to see it similar to this
ClientID Name Address StartDate SalesRep Website
155555 Calvin 123 Fake St 10/10/2013 Tom http://www.fakesite.com
155556 Steve 456 Root Rd 8/5/2013
155557 Kathy 715 Main St 5/5/2010 Jessica http://www.fakesite2.com
155558 Jenny 345 Fake St 9/9/2012 http://www.fakesite3.com
I know this is possible using sql, but I've just usually written scripts to deal with the data after the export. But this time I need to be able to do it in Access so the table can be re-opened 2 months from now and it will re-query the data in the same way.
Let me know if there's anything else I can provide to help get the right result.
ADDON
I took the long way around and made individual queries for each of the UDF's, then consolidated them all by running a query agains't each to place them all in one line. I am still curious how to do this with SQL though because right now I'm in the midst of changing CRM and Accounting software for my organization, and it's become a daunting task.
Here's the query I was using to pull the UDFs onto separate lines like outlined above.
SELECT dbo_AMGR_Client_Tbl.Client_Id, dbo_AMGR_Client_Tbl.Name,
dbo_AMGR_Client_Tbl.Address_Line_1, dbo_AMGR_Client_Tbl.Address_Line_2,
dbo_AMGR_Client_Tbl.City, dbo_AMGR_Client_Tbl.State_Province,
dbo_AMGR_Client_Tbl.Zip_Code, dbo_AMGR_User_Field_Defs_Tbl.Description,
dbo_AMGR_User_Fields_Tbl.DateCol, dbo_AMGR_User_Fields_Tbl.NumericCol,
dbo_AMGR_User_Fields_Tbl.AlphaNumericCol
FROM dbo_AMGR_User_Field_Defs_Tbl INNER JOIN (dbo_AMGR_Client_Tbl INNER JOIN
dbo_AMGR_User_Fields_Tbl ON dbo_AMGR_Client_Tbl.Client_Id =
dbo_AMGR_User_Fields_Tbl.Client_Id) ON (dbo_AMGR_User_Field_Defs_Tbl.Type_Id =
dbo_AMGR_User_Fields_Tbl.Type_Id) AND (dbo_AMGR_User_Field_Defs_Tbl.Code_Id =
dbo_AMGR_User_Fields_Tbl.Code_Id)
GROUP BY dbo_AMGR_Client_Tbl.Name_Type, dbo_AMGR_Client_Tbl.Client_Id,
dbo_AMGR_Client_Tbl.Name, dbo_AMGR_Client_Tbl.Address_Line_1,
dbo_AMGR_Client_Tbl.Address_Line_2, dbo_AMGR_Client_Tbl.City,
dbo_AMGR_Client_Tbl.State_Province, dbo_AMGR_Client_Tbl.Zip_Code,
dbo_AMGR_User_Field_Defs_Tbl.Description, dbo_AMGR_User_Fields_Tbl.DateCol,
dbo_AMGR_User_Fields_Tbl.NumericCol, dbo_AMGR_User_Fields_Tbl.AlphaNumericCol
HAVING (((dbo_AMGR_Client_Tbl.Name_Type)="C") AND ((dbo_AMGR_Client_Tbl.Name) Not Like "*HOUSE*"))
ORDER BY dbo_AMGR_Client_Tbl.Name;

It seems you have multiple rows related to one clientID in the User_Defined_Data table.
Why don't you rebuild that table so that it contains all the fields you require and is one-to one with Clients?
Otherwise you may use CASE statement in your query and filter its contents by description.

Related

Update MS access table using VBA recordset with 2/more inner join sub statements

I have 3 tables in access - tblUsers, tblAssignnent and tblJob. The tblJob is where using a series of calculations in VBA, I arrive at the data dump which is to be worked by my Quality (QC) team. The tblUsers has a list of all our staff and where they are located globally. The tblAssignnent defines which QC team analyst will work on which case processed by our staff globally. For eg. QCID 123 needs to work on all Level 3 cases worked by our staff in China. Accordingly, VBA must allocate QCID 123 to all those rows where individuals in China have worked at Level 3. We have about 20 such QC IDs and an average of 1000 cases worked daily.
Again, the catch here is that tblUsers defines the name and location of each staff - tblAssignnent defines location and level of each staff along with QC ID expected to work. The tblJob has the Name of staff and Level. Check out he shapshot below,
tblUsers
NAME LOCATION
Mathew Shanghai
John New York
Peter Dubai
tblAssignnent
QCID LEVEL LOCATION
123 L3 Shanghai
135 L1 New York
tblJob
QCID LEVEL NAME CASEID
L3 Mathew 001283526
L1 John 827271729
So basically I need QCID to be updated with 123 and 135 in tblJob using VBA. I attempted INNER JOIN within a recordset but I kept getting errors. On search, apparently a VBA recordset may not be able to hold complex statements. Forgive me for my poor formatting as I only have access to my phone now. All my attempts at this code has failed and I will be much obliged for any help extended.
I remain at your disposal for further clarification.
I think I maybe misread this earlier. If you only need the QCID added to the table Job its really simple :
UPDATE (tblJob
INNER JOIN tblAssignment ON tblJob.LEVEL = tblAssignment.LEVEL)
INNER JOIN tblUsers ON (tblUsers.Location = tblAssignment.Location)
AND (tblJob.EName = tblUsers.EName)
SET tblJob.QCID = tblAssignment.QCID

Run a set number of joined select statements under a single sql query

I have a counselling appointment website. Currently I list clients in one table, but also have couples listed by id in a second table for when they book a couples session. ie:
client
id_no first last
564 John Smith
983 Mary Jones
999 Mark Fields
882 Joan Hancock
couple
id_no client1 client2
623 564 983
555 999 882
I would like to write a single select statement, using aliases, which will list out couples on a single line. Up until now, I have been doing a simple join then cleaning up the result using php after running the query, but would like to clean this up in sql so that I get a result like the following
id_no first_1 last_1 first_2 last_2
623 John Smith Mary Jones
555 Mark Fields Joan Hancock
I suspect that sub queries might be involved, but can't for the life of me wrangle them to get this result.
Update
I just tried the following:
SELECT id_no,first_1,last_1,first_2,last_2
FROM ( SELECT a.id_no AS id_no, b.first AS first_1,b.last AS last_1
FROM couple AS a, client AS b WHERE a.client1=b.id_no ) c1
JOIN ( SELECT a.id_no AS id_no, b.first AS first_2,b.last AS last_2
FROM couple AS a, client AS b WHERE a.client2=b.id_no ) c2 ON
(c1.id_no=c2.id_no)
And am getting a message that "Column 'id_no' in field list is ambiguous". Not sure if I am on the right track
You are getting the exception because you did not specified the table alias to id_no as this column belongs to both tables, so SQL is not sure which column to return, so it will throw ambiguous column error.
Also you don't have to use sub queries, you just need to join client table twice with couple table, one for client1 and other one for client2 like below
Select cp.id_no,
cl1.first as first_1,
cl1.last as last_1,
cl2.first as first_2,
cl2.last as last_2
From couple cp
inner join client cl1 on cl1.id_no = cp.client1
inner join client cl2 on cl2.id_no = cp.client2

SQL Server 2008. Take info from two tables and concatenate row values. [duplicate]

This question already has answers here:
Simulating group_concat MySQL function in Microsoft SQL Server 2005?
(12 answers)
Closed 4 years ago.
I have looked at what was marked as the duplicate of this and it is not. I'm pulling from two tables, not one.
First, allow me to say I had nothing to do with the design of this database.
I have two tables that must be joined, and then an unknown amount of rows where the data must be concatenated into one giant string. They are joined by the Record ID.
Item table:
Item RecordID
---------------------
Car A 123
Car B 456
Car C 789
Yes, the words literally cut off in the middle. There should be nothing added between the values, and I also need to keep the commas and other special characters.
Details table:
RecordID Details
--------------------------------
123 black pain
123 t, radials
123 , green le
123 ather, spo
123 rt steerin
123 g wheel, b
123 uilt-in GP
123 S
456 standard
789 black leat
789 her, teles
789 coping ste
789 ering whee
789 l, seven c
789 up holders
789 , heavy du
789 ty mudflap
789 s
What I want to end up with is this:
ItemID RecordID Details
----------------------------------------------------------------------------
Car A 123 black paint, radials, green leather, sport steering wheel, built-in GPS
Car B 456 standard
Car C 789 black leather, telescoping steering wheel, seven cup holders, heavy duty mudflaps
I've looked at all the XML ones and can't figure out how to do this.
Thanks in advance.
There is no guarantee that your STUFF/ FOR XML PATH will produce the results you ask for unless you have an IDENTITY field in your Details table or some other value that you can sort by that will force the order of the Details text.
Usually you could use the STUFF command with an ORDER BY statement
SELECT
Item.Item AS ItemID,
Item.RecordID,
STUFF( (
SELECT
'' + Details
FROM
Details
WHERE
Details.RecordID = Item.RecordID
-- ORDER BY SomeLineIndicator
FOR XML PATH ('')
), 1, 0, '' ) AS Details
FROM
Item
I tried this on my box without the ORDER BY and just so happened to get the result you're asking for, but you really can't rely on these results without a field you can use to force the order.
Please read this post and the linked articles for more information about why you'd need a field for this and why you can't depend on an undetermined internal "index" to take care of it for you: Default row order in SELECT query - SQL Server 2008 vs SQL 2012

Combining almost identical rows into 1

I have a tricky problem that I wouldn't mind a bit of help on, I've made some progress using queries that I've here and elsewhere, but am getting seriously stumped now.
I have a mailing list that has numerous near duplications that I'm trying to combine into one meaningful row, taking data such as this.
Title Forename Surname Address1 Postcode Phone Age Income Ownership Gas
Mrs D Andrews 122 Somewhere BH10 123456 66-70 Homeowner
Ms Diane Andrews 122 Somewhere BH10 123456 £25-40 EDF
and making one row along the lines of
Title Forename Surname Address1 Postcode Phone Age Income Ownership Gas
Mrs Diane Andrews 122 Somewhere BH10 123456 66-70 £25-40 Homeowner EDF
I have over 127 million records, most duplicated with a similar pattern, but no clear logic as was proven when I added an identity field. I also have over 90 columns to consider, so it's a bit of work!
There isn't a clear pattern to the data, so I'm thinking I may have a huge case statement to try to climb over.
Using the following code I can get a decent start on only returning the full name, but with the pattern of data - trying to compare the fields across rows is as follows.
SELECT c1.*
FROM
Mailing c1
JOIN
Mailingc2 ON c1.Telephone1 = c2.Telephone1 AND c1.surname = c2.surname
WHERE
len(c1.Forename) > len(c2.Forename)
AND c2.over_18 <> ''
AND c1.Telephone1 = '123456'
Has anyone got any pointers as to how I should progress please? I'm open to discussion and ideas...
I'm using SQL 2005 and apologies in advance if the tagging is all over the place!
Cheers,
Jon
Would it work by assuming that all persons with the same surname and phone number (Do all persons have a phone?) were the same person?
INSERT INTO newtable <fieldnames>
SELECT lastname,phone,max(field3),max(field4)....
FROM oldtable
GROUP BY lastname,phone
But that would collapse John Smith and Jack Smith living together into one person.
Perhaps you should consider outsourcing it to a data-entry sweatshop somewhere, adter you have preprocessed the data. :-)
And/or be prepared to take the flack for mistaken bundling.
Perhaps adding something like "To improve our green footprint, we have merged x listings on your adress together. If you would like separate mailings, please contact us"

Crystal reports - missing fields

using Crystal reports 10 linked to an excel document. Would like to pull the dinner field but also pull country and Company name from row that dont have it, this are linked via Bookingref. Example below. I've tried sub-reports and supressing unwanted fields but can't get it right. Also I can't make changes in excel doc as it's 1000+ records, which is exported from an online system weekly.
Id BookingRef Country CompanyName Surname Forname Dinner
1 001 UK Company1 John Andrews
2 001 Mary Jane 1
3 001 Tom Andrews 1
4 002 Germany Company2 Lee Jones
5 003 Germany Company3 Peter Lee 1
6 003 Sofie Lee 1
OK I am not sure I understand the full extent of your problem but let's start with the Country and Company name and see if I can get you moving forward. Instead of putting the Country field directly on the report you could use a formula field and do something like this:
IF {#BookingRef} = "001" Then
"UK"
Else IF {#BookingRef} = "002" Then
"Germany"
Else
"Unnamed"
Now you just put the formula field where the country field used to be and it will put the right country in bases on the BookingRef code. This, however, is only practical if you are working with a small number of Country / Company Names or possibly a big list that never changes although I would caution against the latter.
The other thing you could do is create a table in any database that holds the BookingRef, Company and Country values, link the BookingRef fields from both "databases" and then just drop the fields on your report.
If I am missing the point of your question please be real specific about what it is you are trying to accomplish and what is and is not working in your current solution.