Two group by tables stich another table - sql

I have 3 tables I need to put together.
The first table is my main transaction table where I need to get distinct transaction id numbers and company id. It has all the important keys. The transaction ids are not unique.
The second table has item info which is linked to transaction id numbers which are not unique and I need to pull items.
The third table has company info which has company id.
Now I've sold some of these with the first one through a group by id. The second through a subquery which creates unique ids and joins onto the first one.
The issue I'm having is the third one by company. I cannot seem to create a query that works in the above combinations. Any ideas?
As suggested here is my code. It works but that's because for the company I used count which doesn't give the correct number. How else can I get the company number to come out correct?
SELECT
dep.ItemIDAPK,
dep.TotalOne,
dep.company,
company.vendname,
appd.ItemIDAPK,
appd.ItemName
FROM (
SELECT
csi.ItemIDAPK,
sum(f.TotalOne) as TotalOne,
count(f.DimCurrentcompanyID) company
FROM dbo.ReportOne F with (nolock)
INNER JOIN dbo.DSaleItem csi with (nolock)
on f.DSaleItemID = csi.DSaleItemID
INNER JOIN dbo.DimCurrentcompany cv
ON f.DimCurrentcompanyID = cv.DimCurrentcompanyID
INNER JOIN dbo.DimDate dat
on f.DimDateID = dat.DimDateID
where (
dat.date >='2013-01-29 00:00:00.000'
and dat.date <= '2013-01-30 00:00:00.000'
)
GROUP BY csi.ItemIDAPK
) as dep
INNER JOIN (
SELECT
vend.DimCurrentcompanyID,
vend.Name vendname
FROM dbo.DimCurrentcompany vend
) As company
on dep.company = company.DimCurrentcompanyID
INNER JOIN (
SELECT
c2.ItemIDAPK,
ItemName
FROM (
SELECT DISTINCT ItemIDAPK
FROM dbo.dimitem AS C
) AS c1
JOIN dbo.dimitem AS c2 ON c1.ItemIDAPK = c2.ItemIDAPK
) as appd
ON dep.ItemIDAPK = appd.ItemIDAPK
For further information my output is the following example, I know the code executes and the companyid is incorrect as I just put it with a (count) in their to make the above code execute:
Current Results:
Item Number TLS CompanyID Company Name Item Number Item Name
111111 300 303 Johnson Corp 29323 Soap
Proposed Results:
Item Number TLS CompanyID Company Name Item Number Item Name
111111 300 29 Johnson Corp 29323 Soap

Related

Listing Pairs on same table with different criteria on Oracle Sql

I need to list pairs of customer names as follows;
> CUSTOMER_FIRST_NAME, CUSTOMER_LAST_NAME, CUSTOMER_FIRST_NAME, CUSTOMER_LAST_NAME
such that each pair of customers has the same zip code (which is also in the customers table).
On the task there is a hint which says
HINT: Your output should have four columns: CUSTOMER_FIRST_NAME, CUSTOMER_LAST_NAME, CUSTOMER_FIRST_NAME, CUSTOMER_LAST_NAME
This is what I have written so far:
SELECT DISTINCT CUSTOMER_FIRST_NAME, CUSTOMER_LAST_NAME, CUSTOMER_FIRST_NAME, CUSTOMER_LAST_NAME
FROM CUSTOMERS
WHERE CUSTOMER_ZIP = CUSTOMER_ZIP
But I am not sure how to continue since I've only started learning SQL yesterday. I have also tried to Join the same table which resulted in ambiguity errors.
Update#1:
I've written this code using aliases as suggested by #kpater87
SELECT DISTINCT C1.CUSTOMER_FIRST_NAME, C1.CUSTOMER_LAST_NAME , C2.CUSTOMER_FIRST_NAME, C2.CUSTOMER_LAST_NAME
FROM CUSTOMERS C1
INNER JOIN CUSTOMERS C2
ON C1.CUSTOMER_ZIP = C2.CUSTOMER_ZIP
But even though I have a distinct statement it will show duplicate data. Is this to be expected or am I missing something?
Your updated query looks fine. The only problem in your query is it will be joining also the same records.
If you have a primary key in the table you can improve your query by adding WHERE condition:
SELECT DISTINCT C1.CUSTOMER_FIRST_NAME,
C1.CUSTOMER_LAST_NAME ,
C2.CUSTOMER_FIRST_NAME,
C2.CUSTOMER_LAST_NAME
FROM CUSTOMERS C1
INNER JOIN CUSTOMERS C2
ON C1.CUSTOMER_ZIP = C2.CUSTOMER_ZIP
WHERE C1.PK <> C2.PK;
PK - is a column being a primary key in the table.
If you don't have primary key you can try this one:
SELECT C1.CUSTOMER_FIRST_NAME,
C1.CUSTOMER_LAST_NAME ,
C2.CUSTOMER_FIRST_NAME,
C2.CUSTOMER_LAST_NAME
FROM CUSTOMERS C1
INNER JOIN CUSTOMERS C2
ON C1.CUSTOMER_ZIP = C2.CUSTOMER_ZIP
WHERE C1.CUSTOMER_FIRST_NAME <> C2.CUSTOMER_FIRST_NAME
AND C2.CUSTOMER_LAST_NAME <> C2.CUSTOMER_LAST_NAME
But there still be a problem that in your output you will get e.g.
Mary Smith James Bond
James Bond Mary Smith
To remove permutations:
SELECT C1.CUSTOMER_FIRST_NAME,
C1.CUSTOMER_LAST_NAME ,
C2.CUSTOMER_FIRST_NAME,
C2.CUSTOMER_LAST_NAME,
C1.CUSTOMER_ZIP
FROM T_CUSTOMERS C1
LEFT JOIN T_CUSTOMERS C2
ON (C1.CUSTOMER_ZIP = C2.CUSTOMER_ZIP
AND
C1.CUSTOMER_NUMBER > C2.CUSTOMER_NUMBER );
See also: SQL: self join using each rows only once

SQL Exclude results from join or subquery where column names don't match up with multiple tables

Ok, I'm working with an existing database (cannot edit the tables, columns, etc.) I am asked to create a report with the data for clients. This worked fine until we needed to create an exclusions group for certain clients.
There are 8 tables that need to be parsed for information in the database to execute this query properly. I've "simplified" it to 6 tables as best as I can.
The tables below are the existing tables, in the best order that I could come up with.
Table: Clients
ClientKey ClientNo ClientName
1 12345 ABC
2 12346 DEF
3 12347 GHI
4 12348 JKL
5 12349 MNO
6 12350 PQR
Table: ClientGroup
ClientKey GroupCode GroupValue
12345 EXCLUSIONSGROUP EXCLUDE
12346 EXCLUSIONSGROUP EXCLUDE
12347 OTHERSTUFF SOMETHING
Table: Groups
GroupCode GroupCodeKey
EXCLUSIONSGROUP 25
OTHERSTUFF 14
Table: GroupValues
GroupCode GroupValue
EXCLUSIONSGROUP EXCLUDE
OTHERSTUFF SOMETHING
EXCLUSIONSGROUP SOMETHING
Table: Images
FileKey Filename
987654 NULL
987653 Filename.jpg
987652 Filename.jpg
987651 NULL
987650 NULL
Table: Files
FileKey ClientKey
987654 12345
987653 12345
987652 12346
987651 12347
987650 12347
To better explain these tables:
Clients holds our clients
ClientGroup holds a list of which clients belong to which groups and the value that this client was assigned in that group (clients can be assigned multiple groups, and/or multiple values for a group)
Groups holds a list of the groups that exist as well as the GroupCodeKey. This table is important to refer to because the GroupCode values can change, so referring to '25' for example is the best way to access the proper GroupCode
GroupValues holds a list of all the possible GroupValues that can be assigned to a GroupCode (Group). They may be added, removed, changed.
Images points to the Files table through the FileKey column which points to the Clients table through the ClientKey column. The Images table tells us if a client's file has an image or not (defined by NULL if it does not exist)
Files contains a list of all documents that belong to a client. A client can (and most likely will) have multiple documents/files.
What I need to do:
I need to find all instances where the Filename in the Images table is NULL and where the Client is NOT in the ClientGroup table with a GroupValue of GroupValues(table)GroupValue(column) equal to 'EXCLUDE' and in the GroupCode of Groups(table)GroupCode(column) equal to Groups(table)GroupCodeKey(column) of '25'
In the following code, ignore columns that are unseen in the tables above, they exist, however to simplify the code and tables above, I've removed them from the code. They are still relevant to mention in the code below under select as both queries pull different columns' information from the database which prevents me from doing an EXCEPT between both queries
The current code (simplified) I have to get all the Clients with NULL Images is:
SELECT f.FileKey AS fkey, f.fNo AS fno, f.fDate AS fdate, cli.ClientNo AS clientno, cli.ClientName AS clientname, /*OTHER TABLE STUFF*/
FROM Files as f
LEFT JOIN Images as img
ON f.FileKey=img.FileKey
/*OTHER LEFT JOINS AND TABLES HERE RETURNING OTHER DATA*/
WHERE
img.[Filename] IS NULL
ORDER BY f.FileKey DESC
The current code I have to get all the Clients that are in the group with a GroupCodeKey of '25' and with a GroupValue of 'EXCEPT' is:
SELECT cli.ClientNo AS clientno, cli.ClientName AS clientname
FROM Clients AS cli
LEFT JOIN ClientGroup AS cg
ON cg.ClientKey = cli.ClientKey
LEFT JOIN Groups AS gc
ON gc.GroupCode = cg.GroupCode
LEFT JOIN GroupValue AS gv
ON gv.GroupCode = gc.GroupCode
WHERE
gc.GroupCodeKey='25' AND
gv.GroupValue='EXCLUDE'
Both above queries work exactly as anticipated on their own.
How would I combine these queries to give me the desired output?
The desired output (according to the tables above and their contents) would be to have the information that matches the first query minus the second one:
ClientNo:123457
ClientName:GHI
FileKey:987651
AND
ClientNo:123457
ClientName:GHI
FileKey:987650
Both these results match a client not belonging to the exceptions group '25' with value of 'EXCLUDE' and both FileKeys (987651 and 987650) have Filename set to NULL
I have tried to join all the tables, but cannot seem to properly create the query (I get either no results or I get results for the clients in the exception group only - whereas I need the ones not in the exceptions group). I have also tried creating a subquery, but I couldn't seem to get that to work either...
Any help regarding this is much appreciated.
Thanks!
Not sure if I have all the criteria right, but the general form of what you want can be gotten using NOT EXISTS
SELECT clientno, clientname, fkey, /*OTHER TABLE STUFF*/
FROM (
SELECT f.FileKey AS fkey, f.fNo AS fno, f.fDate AS fdate, cli.ClientNo AS clientno, cli.ClientName AS clientname, /*OTHER TABLE STUFF*/
FROM Files AS f
LEFT JOIN Images AS img
ON f.FileKey=img.FileKey
/*OTHER LEFT JOINS AND TABLES HERE RETURNING OTHER DATA*/
WHERE
img.[Filename] IS NULL
) incl
WHERE NOT EXISTS (
SELECT * FROM(
SELECT cli.ClientNo AS clientno, cli.ClientName AS clientname
FROM Clients AS cli
LEFT JOIN ClientGroup AS cg
ON cg.ClientKey = cli.ClientKey
LEFT JOIN Groups AS gc
ON gc.GroupCode = cg.GroupCode
LEFT JOIN GroupValue AS gv
ON gv.GroupCode = gc.GroupCode
WHERE
gc.GroupCodeKey='25' AND
gv.GroupValue='EXCLUDE'
) excl
WHERE excl.clientno = incl.ClientNo
AND excl.clientname = incl.ClientName
)
ORDER BY fkey DESC
SELECT im.FileKey
FROM Images AS im
INNER JOIN Files as Fi ON im.filekey = fi.filekey
--NOW THAT WE KNOW ALL CLIENT KEYS THAT MEET THE REQUIREMENTS WE NEED TO GO GET THE FILEKEY
INNER JOIN (
-- FIND ALL IMAGES WHERE FILE IS NOT NULL
SELECT F.clientKey
FROM images AS i
INNER JOIN files AS F on f.fileKey = i.fileKey
WHERE i.filename IS NULL
INTERSECT--GRAB THE INTERSECT BECAUSE WE WANT TO KNOW ALL CLIENTKEYS THAT MEET THE BELOW REQUIREMENTS
--FIND ALL CLIENTS THAT ARE NOT IN EXCLUDED AND IN THE GROUPS TABLE WITH GROUPCODE =25
SELECT C.ClientKey
FROM CLIENTS AS C
INNER JOIN CLientGroup AS CG ON C.clientKey = cg.clientkey AND cg.groupvalue != 'EXCLUDE'
INNER JOIN Groups AS g on CG.groupCode = g.groupCode AND g.groupCodeKey = '25') AS x on x.clientkey = fi.clientkey
I believe this will get you what you want(un tested)

SQL Inner join in a nested select statement

I'm trying to do an inner join in a nested select statement. Basically, There are first and last reason IDs that produce a certain number (EX: 200). In another table, there are definitions for the IDs. I'm trying to pull the Last ID, along with the corresponding comment for whatever is pulled (EX: 200 - Patient Cancelled), then the first ID and the comment for whatever ID it is.
This is what I have so far:
Select BUSN_ID
AREA_NAME
DATE
AREA_STATUS
(Select B.REASON_ID
A.LAST_REASON_ID
FROM BUSN_INFO A, BUSN_REASONS B
WHERE A.LAST_REASON _ID=B.REASON_ID,
(Select B.REASON_ID
A. FIRST_REASON_ID
FROM BUSN_INFO A, BUSN_REASONS B
WHERE A_FIRST_REASON_ID = B.REASON_ID)
FROM BUSN_INFO
I believe an inner join is best, but I'm stuck on how it would actually work.
Required result would look like (this is example dummy data):
First ID -- Busn Reason -- Last ID -- Busn Reason
1 Patient Sick 2 Patient Cancelled
2 Patient Cancelled 2 Patient Cancelled
3 Patient No Show 1 Patient Sick
Justin_Cave's SECOND example is the way I used to solve this problem.
If you want to use inline select statements, your inline select has to select a single column and should just join back to the table that is the basis of your query. In the query you posted, you're selecting the same numeric identifier multiple times. My guess is that you really want to query a string column from the lookup table-- I'll assume that the column is called reason_description
Select BUSN_ID,
AREA_NAME,
DATE,
AREA_STATUS,
a.last_reason_id,
(Select B.REASON_description
FROM BUSN_REASONS B
WHERE A.LAST_REASON_ID=B.REASON_ID),
a.first_reason_id,
(Select B.REASON_description
FROM BUSN_REASONS B
WHERE A.FIRST_REASON_ID = B.REASON_ID)
FROM BUSN_INFO A
More conventionally, though, you'd just join to the busn_reasons table twice
SELECT i.busn_id,
i.area_name,
i.date,
i.area_status,
i.last_reason_id,
last_reason.reason_description,
i.first_reason_id,
first_reason.reason_description
FROM busn_info i
JOIN busn_reason first_reason
ON( i.first_reason_id = first_reason.reason_id )
JOIN busn_reason last_reason
ON( i.last_reason_id = last_reason.reason_id )

Update multiple row values to same row and different columns

I was trying to update table columns from another table.
In person table, there can be multiple contact persons with same inst_id.
I have a firm table, which will have latest 2 contact details from person table.
I am expecting the firm tables as below:
If there is only one contact person, update person1 and email1. If there are 2, update both. If there is 3, discard the 3rd one.
Can someone help me on this?
This should work:
;with cte (rn, id, inst_id, person_name, email) as (
select row_number() over (partition by inst_id order by id) rn, *
from person
)
update f
set
person1 = cte1.person_name,
email1 = cte1.email,
person2 = cte2.person_name,
email2 = cte2.email
from firm f
left join cte cte1 on f.inst_id = cte1.inst_id and cte1.rn = 1
left join cte cte2 on f.inst_id = cte2.inst_id and cte2.rn = 2
The common table expression (cte) used as a source for the update numbers rows in the person table, partitioned by inst_id, and then the update joins the cte twice (for top 1 and top 2).
Sample SQL Fiddle
I think you don't have to bother yourself with this update, if you rethink your database structure. One great advantage of relational databases is, that you don't need to store the same data several times in several tables, but have one single table for one kind of data (like the person's table in your case) and then reference it (by relationships or foreign keys for example).
So what does this mean for your example? I suggest, to create a institution's table where you insert two attributes like contactperson1 and contactperson2: but dont't insert all the contact details (like email and name), just the primary key of the person and make it a foreign key.
So you got a table 'Person', that should look something like this:
ID INSTITUTION_ID NAME EMAIL
1 100 abc abc#inst.com
2 101 efg efg#xym.com
3 101 ijk ijk#fg.com
4 101 rtw rtw#rtw.com
...
And a table "Institution" like:
ID CONTACTPERSON1 CONTACTPERSON2
100 1 NULL
101 2 3
...
If you now want to change the email adress, just update the person's table. You don't need to update the firm's table.
And how do you get your desired "table" with the two contact persons' details? Just make a query:
SELECT i.id, p1.name, p1.email, p2.name, p2.email
FROM institution i LEFT OUTER JOIN person p1 ON (i.contactperson1 = p1.id)
LEFT OUTER JOIN person p2 ON (i.contactperson2 = p2.id)
If you need this query often and access it like a "table" just store it as a view.

Selecting from table with categories of people

I created a database in ms sql , in the database I have three category of persons namely staff, customers, suppliers whom I stored in different tables create serial unique id for each.
Now these persons id are stored under person_id and a column names person type which stores whether its a staff, custimer or supplier in the transaction table, The problem lies in selecting the records from the transaction table like this pseudo code
Select t.*,s.na as staff,sp.name as supplier, c.name as customer
From Trans t
left join Staff s on s.id = t.pid
left join Suppliers sp on sp.id = t.pid
left join Customers c on c.id = t.pid
This returns one row, instead of at least 3 or more, How do I solve this problem
My trans table
person_id Person_type Trans_id
1 staff 1
1 customer 2
2 customer 3
3 suppler 4
1 staff 5
Expected output
person_name Trans_id
james 1
mark 2
dan 3
jude 4
james 5
Staff, Customers, and suppliers are stored in their different tables
That's what the Join does, combine data from multiple tables into one result row. If you want to "keep the rows", not combine them, you can use UNION
(
Select t.* From Trans t
left join Staff s on s.id = t.pid
)
UNION
(
Select t.* From Trans t
left join Suppliers sp on sp.id = t.pid
)
UNION
(
Select t.* From Trans t
left join Customers c on c.id = t.pid
)
This will get you the multiple rows you want BUT still not sure you have defined it right. I see you are only taking columns from Trans, so you're not getting any data from the other tables. And you're doing left outer joins so the other tables won't affect the selection. So I think it's just that same as selecting from just Trans.
If what you want is data from Trans where there is corresponding entry in the other tables, then do the UNION, but also change the outer joins to inner.