Query of queries with same field headings - MS Access - sql

I've got a few queries (20+) which all return the following three columns:
Building | Room | Other
all of which are text fields. I'd like to take all of those queries and combine them; so I'd like to see what the queries return as a whole.
For example, if I had a query SELECT Building, Room, Other FROM tblOne WHERE Room=10 along with SELECT Building, Room, Other FROM tblOne WHERE Building=20, how might I combine those two into one? Obviously this is a very simple example and my real queries are much more complicated, so writing them as 1 query is not feasible.
I'd like the above example to output:
Building | Room | Other
```````````````````````
20 | 1 | Some Stuff
20 | 10 | Some More
5 | 10 | Some Other
15 | 10 | Some Extra
20 | 5 | Some Text
All the ways I've tried have come up with the error that "Building, Room and Other could refer to more than one table" (aka it doesn't want to combine them under one heading). What is the SQL syntax to fix this?

SELECT Building, Room, Other FROM tblOne WHERE Room=10
UNION ALL
SELECT Building, Room, Other FROM tblOne WHERE Building=20

Combine these two Query with the help of UNION ALL && UNION like this
Query 1
SELECT Building, Room, Other FROM tblOne WHERE Room=10
UNION ALL
SELECT Building, Room, Other FROM tblOne WHERE Building=20
Query 2
SELECT Building, Room, Other FROM tblOne WHERE Room=10
UNION
SELECT Building, Room, Other FROM tblOne WHERE Building=20
Notice
The UNION operator is used to combine the result-set of two or more SELECT statements.
Each SELECT statement within the UNION must have the same number of columns. The columns must also have similar data types. Also, the columns in each SELECT statement must be in the same order.
The UNION operator selects only distinct values by default. To allow duplicate values, use UNION ALL.

Related

How to find table names having ID (primary key) of a certain value in a hierarchy of tables?

I use Oracle 11g and have a massive number of tables representing inheritance, where a base parent table has a primary key NUMBER ID. The subsequent tables inherit from it, representing through the shared primary key NUMBER ID. Let's assume there is a multiple layers of such inheritance.
To have a clear picture, let's work with the following simplified structure and assume the hierarchy is quite complex:
- TABLE FOOD
- TABLE FRUIT
- TABLE CYTRUS
- TABLE ORANGE
- TABLE GREPFRUIT
- TABLE VEGETABLE
- TABLE MEAT
- TABLE BEEF
- TABLE SIRLOIN
- TABLE RIB EYE
- TABLE CHICKEN
This is not taxative, regardless of how dumb the example is, assume such a multi-layered hierarchy using Class Table Inheritance (aka Table Per Type Inheritance).
If you want to insert a record to a table ORANGE having a certain generated ID, there must be inserted records to the parent tables (CYTRUS, FRUIT and FOOD) as well. Assume an ORM engine takes care after this as keeping such consistency would be very complex.
Let's also assume each of the tables in the hierarchy ends with a certain word (let's say FOOD: FRUIT_FOOD, CYTRUS_FOOD etc.) - I didn't include it to the chart above for sake of clarity.
Question: I have found a record in FOOD table with ID = 123 based on certain criteria. Thanks to the hierarchical structure, how do I find what tables contain the record with the very same ID using SQL only? I.e. my goal is to find out what * the lowest type in the hierarchy* the certain ID is related to.
Note: If you have also an answer for a newer version of Oracle, don't hesitate to include it as long as others might find it useful.
Assuming all these tables have a column ID but you may adjust based on the example.
Q1. what tables contain the record with the very same ID using SQL only
You could use a series unions to determine this eg.
SELECT
id,
table_type,
heirarchy_level
FROM (
SELECT ID, 'FOOD', 1 FROM FOOD
UNION ALL
SELECT ID,'FRUIT',2 FROM FRUIT
UNION ALL
SELECT ID,'CYTRUS',3 FROM CYTRUS
UNION ALL
SELECT ID,'ORANGE',4 FROM ORANGE
UNION ALL
SELECT ID,'GREPFRUIT',4 FROM GREPFRUIT
UNION ALL
SELECT ID,'VEGETABLE',2 FROM VEGETABLE
UNION ALL
SELECT ID,'MEAT',2 FROM MEAT
UNION ALL
SELECT ID,'BEEF',3 FROM BEEF
UNION ALL
SELECT ID,'SIRLOIN',4 FROM SIRLOIN
UNION ALL
SELECT ID,'RIBEYE',4 FROM RIBEYE
UNION ALL
SELECT ID,'CHICKEN',3 FROM CHICKEN
) t
WHERE
id = 123
This would return a table with the id=123 but more importantly a table listing all tables where the record was present along with the depth/level in the hierarchy. You could then use MAX or order by to determine the deepest level
Q2. what is the lowest type in the hierarchy the certain ID is related to
This would return only one record with the lowest type
SELECT
id,
table_type,
heirarchy_level
FROM (
SELECT ID, 'FOOD', 1 FROM FOOD
UNION ALL
SELECT ID,'FRUIT',2 FROM FRUIT
UNION ALL
SELECT ID,'CYTRUS',3 FROM CYTRUS
UNION ALL
SELECT ID,'ORANGE',4 FROM ORANGE
UNION ALL
SELECT ID,'GREPFRUIT',4 FROM GREPFRUIT
UNION ALL
SELECT ID,'VEGETABLE',2 FROM VEGETABLE
UNION ALL
SELECT ID,'MEAT',2 FROM MEAT
UNION ALL
SELECT ID,'BEEF',3 FROM BEEF
UNION ALL
SELECT ID,'SIRLOIN',4 FROM SIRLOIN
UNION ALL
SELECT ID,'RIBEYE',4 FROM RIBEYE
UNION ALL
SELECT ID,'CHICKEN',3 FROM CHICKEN
) t
WHERE
id = 123
ORDER BY
heirarchy_level desc
LIMIT 1

TypeORM & Postgres: Count only unique distinct values from multiple columns

I have various SQL queries, which return me unique / distinct value from DB, (or count them),
like:
SELECT buyer as counterparty
FROM public.order
UNION
SELECT seller as counterparty
FROM public.order
or
SELECT COUNT(*)
FROM (
SELECT DISTINCT p
FROM public.order
CROSS JOIN LATERAL (VALUES(seller),(buyer)) AS C(p)
) AS internalQuery
Example structure of my table:
id buyer seller
0 A B
1 B A
2 B D
3 D A
4 A D
Desired result:
3 or A,B,D
I'd like to rewrite them with TypORM query builder, but I can't figure out, how to replace CROSS JOIN LATERAL (VALUES(seller),(buyer)) AS C(p) or UNION in my case. TypeORM is pretty poor with examples and doc coverage in this case.
Does there any option with that?
I have seen various methods like .getCount and .distinct(true) which could help me and easily find the solution for one column.
So I understood, that if I want to find the exact number, instead of doc results, I should use .getCount instead of .getMany
But I can't understand, how to select (and unite) values from multiple columns via typeORM to receive distinct values from multiple columns.
I am working with PostgrSQL, so when I am trying:
const query = repository.createQueryBuilder('order')
.distinctOn(['buyer', 'seller'])
.limit(100)
.getMany()
I receive docs with each distinct value in each field, so instead of 3 I get 6 values (3 distinct by column1, and 3 by column2)

SQL PIVOT, JOIN, and aggregate function to generate report

I am working on creating a report which will incorporate data across 4 different tables. For this question, I have consolidated the data into 2 tables and am stuck trying to figure out exactly how to create this report using PIVOT.
The report will hold the top 5 strengths of an employee based on the Clifton StrengthsFinder assessment.
This is the table with the Names of the Clifton Strengths (34 rows total):
As mentioned, each employee has 5 strengths:
I would like to use PIVOT to generate a table which will ultimately look like this:
With a twist, I don't need the Team Name as a Row, it should be a column. The Count at the bottom and Themes at the top (Executing, Influencing, etc) can be ignored.
The columns of the table I'm trying to output are PersonFk, PersonName, TeamName, Achiever, Arranger, etc... (34 Strengths) and each row of the table with Values (personfk, name, team, 1 if person has the strength, 0 otherwise). This table should be SQL, not excel (sorry, just the best example I have on hand without spending an hour learning how to use Paint or something).
I'm not very familiar with aggregate functions, and am just now getting into the more complex SQL queries..
Interesting. Pivot requires an aggregate function to build the 1-5 values, so you'll have to rewrite your inner query probably as a union, and use MAX() as a throwaway aggregate function (throwaway because every record should be unique, so MAX, MIN, SUM, etc. should all return the same value:
SELECT * INTO #newblah from (
SELECT PersonFK, 1 as StrengthIndex, Strength1 as Strength from blah UNION ALL
SELECT PersonFK, 2 as StrengthIndex, Strength2 as Strength from blah UNION ALL
SELECT PersonFK, 3 as StrengthIndex, Strength3 as Strength from blah UNION ALL
SELECT PersonFK, 4 as StrengthIndex, Strength4 as Strength from blah UNION ALL
SELECT PersonFK, 5 as StrengthIndex, Strength5 as Strength from blah
)
Then
select PersonFK, [Achiever], [Activator], [Adaptability], [Analytical], [Belief] .....
from
(
select PersonFK, StrengthIndex, Strength
from #newblah
) pivotsource
pivot
(
max(StrengthIndex)
for Strength in ([Achiever], [Activator], [Adaptability], [Analytical], [Belief] ..... )
) myPivot;
The result of that query should be able to be joined back to your other tables to get the Person name, Strength Category, and Team name, so I'll leave that to you. You don't HAVE to do the first join as a temporary table -- you could do it as a subselect inline, so this could all be done in one SQL query, but that seems painful if you can avoid it.
Use one of the techniques from this post. For your purposes, you may want to use a delimiter in your column name to the tune of 'StrngthTheme-Strength', which your web report will then parse for the headers.

I DISTINCTly hate MySQL (help building a query)

This is staight forward I believe:
I have a table with 30,000 rows. When I SELECT DISTINCT 'location' FROM myTable it returns 21,000 rows, about what I'd expect, but it only returns that one column.
What I want is to move those to a new table, but the whole row for each match.
My best guess is something like SELECT * from (SELECT DISTINCT 'location' FROM myTable) or something like that, but it says I have a vague syntax error.
Is there a good way to grab the rest of each DISTINCT row and move it to a new table all in one go?
SELECT * FROM myTable GROUP BY `location`
or if you want to move to another table
CREATE TABLE foo AS SELECT * FROM myTable GROUP BY `location`
Distinct means for the entire row returned. So you can simply use
SELECT DISTINCT * FROM myTable GROUP BY 'location'
Using Distinct on a single column doesn't make a lot of sense. Let's say I have the following simple set
-id- -location-
1 store
2 store
3 home
if there were some sort of query that returned all columns, but just distinct on location, which row would be returned? 1 or 2? Should it just pick one at random? Because of this, DISTINCT works for all columns in the result set returned.
Well, first you need to decide what you really want returned.
The problem is that, presumably, for some of the location values in your table there are different values in the other columns even when the location value is the same:
Location OtherCol StillOtherCol
Place1 1 Fred
Place1 89 Fred
Place1 1 Joe
In that case, which of the three rows do you want to select? When you talk about a DISTINCT Location, you're condensing those three rows of different data into a single row, there's no meaning to moving the original rows from the original table into a new table since those original rows no longer exist in your DISTINCT result set. (If all the other columns are always the same for a given Location, your problem is easier: Just SELECT DISTINCT * FROM YourTable).
If you don't care which values come from the other columns you can use a (bad, IMHO) MySQL extension to SQL and do:
SELECT * FROM YourTable GROUP BY Location
which will give a result set with one row per location and values for the other columns derived from the original data in an undefined fashion.
Multiple rows with identical values in all columns don't have any sense. OK - the question might be a way to correct exactly that situation.
Considering this table, with id being the PK:
kram=# select * from foba;
id | no | name
----+----+---------------
2 | 1 | a
3 | 1 | b
4 | 2 | c
5 | 2 | a,b,c,d,e,f,g
you may extract a sample for every single no (:=location) by grouping over that column, and selecting the row with minimum PK (for example):
SELECT * FROM foba WHERE id IN (SELECT min (id) FROM foba GROUP BY no);
id | no | name
----+----+------
2 | 1 | a
4 | 2 | c

Reporting against a CSV field in a SQL server 2005 DB

Ok so I am writing a report against a third party database which is in sql server 2005. For the most part its normalized except for one field in one table. They have a table of users (which includes groups.) This table has a UserID field (PK), a IsGroup field (bit) , a members field (text) this members field has a comma separated list of all the members of this group or (if not a group) a comma separated list of the groups this member belongs to.
The question is what is the best way to write a stored procedure that displays what users are in what groups? I have a function that parses out the ids into a table. So the best way I could come up with was to create a cursor that cycles through each group and parse out the userid, write them to a temp table (with the group id) and then select out from the temp table?
UserTable
Example:
ID|IsGroup|Name|Members
1|True|Admin|3
2|True|Power|3,4
3|False|Bob|1,3
4|False|Susan|2
5|True|Normal|6
6|False|Bill|5
I want my query to show:
GroupID|UserID
1|3
2|3
2|4
5|6
Hope that makes sense...
If you have (or could create) a separate table containing the groups you could join it with the users table and match them with the charindex function with comma padding of your data on both sides. I would test the performance of this method with some fairly extreme workloads before deploying. However, it does have the advantage of being self-contained and simple. Note that changing the example to use a cross-join with a where clause produces the exact same execution plan as this one.
Example with data:
SELECT *
FROM (SELECT 1 AS ID,
'1,2,3' AS MEMBERS
UNION
SELECT 2,
'2'
UNION
SELECT 3,
'3,1'
UNION
SELECT 4,
'2,1') USERS
LEFT JOIN (SELECT '1' AS MEMBER
UNION
SELECT '2'
UNION
SELECT '3'
UNION
SELECT '4') GROUPS
ON CHARINDEX(',' + GROUPS.MEMBER + ',',',' + USERS.MEMBERS + ',') > 0
Results:
id members group
1 1,2,3 1
1 1,2,3 2
1 1,2,3 3
2 2 2
3 3,1 1
3 3,1 3
4 2,1 1
4 2,1 2
Your technique will probably be the best method.