Sorry if the title was sort of vague was unsure how to phrase it.
I currently am choosing values for a field from table like so (clickable SqlFiddle link included):
`Select `ID`,IF(`SpecificationID` is NULL,'0', `SpecificationID`) from Orders;`
http://www.sqlfiddle.com/#!9/b8108b/8
Which as you can see pulled the SpecificationID from the Orders table and if it found a NULL pulled 0. I get that I could/should make the default values in my table = 0 yet to do so would require multiple code changes so this was the easiest way to pull 0 for NULL values which I ultimately need for this process.
It turned out that Orders can have multiple Specifications so I created a Look-Up-Table with OrderID and SpecificationID
My new query therefor looks liks this:
Select `OrderID`,`SpecificationID` from LUT_Orders_Specifications
order by OrderID;
http://www.sqlfiddle.com/#!9/b8108b/9
The issue is that since the LUT only stores values for records with an OrderID I don't get OrderIDs which have no values and therefore don't get 0 for them.
I am unsure how/if I can do a Join that will get the values from the LUT and also return 0 for the records that are not in the LUT.
I know how to select IDs that are not in a table e.g.
Select ID from Orders where ID not in
(Select T1.OrderID from LUT_Orders_Specifications T1
Inner Join Orders T2
on T1.OrderID=T2.ID)
http://www.sqlfiddle.com/#!9/b8108b/15
But I am unclear how I can combine the processes so I am grabbing all the specification values for a single order and a 0 value for an order that has no specifications.
Related
I would like to list in table (staging) the number of related records from table (studies).
So far this statement works well but returns only the rows where there are >0 related records:
SELECT staging.*,
COUNT(studies.PMID) AS refcount
FROM studies
LEFT JOIN staging
ON studies.rs_number = staging.rs
GROUP BY staging.idstaging;
How can I adjust this statement to list ALL rows in table (staging) including where there are zero or null related records from table (studies)?
Thank you
You have the tables in the wrong order in the LEFT JOIN:
SELECT staging.*, COUNT(studies.PMID) AS refcount
FROM staging LEFT JOIN
studies
ON studies.rs_number = staging.rs
GROUP BY staging.idstaging;
LEFT JOIN keeps everything in the first ("left") table and all matching rows in the second. If you want to keep everything in the staging table, then put it first.
And, in case anyone wants to complain about the use of staging.* with GROUP BY. This particular usage is (presumably) ANSI compliant because staging.idstaging is (presumably) a unique id in that table.
I have three tables, items, values, and properties, their structure....
Items
id
title
desc
timestamp
Values
id
value
itemID
propID
Properties
id
name
desc
timestamp
Essentially, with this structure I can create an item, and then assign it any property or value. But I'm running into an issue of how I can search for existing items based on properties and values.
Such that, if I had an item, with a composite key dumped into this, if it were a normal table, I could so "SELECT * FROM items WHERE key1 = 'val1' AND key2 = 'val2'", but I can't figure out how to emulate a search like that, with this kind of structure. Does anyone else have any ideas?
This is for a system I was thrown into, so changing the layout of the tables may not be something I'll be given permission to do.
EDIT: I could break this into multiple steps, but the solutions I'm currently looking at will be slow and could becoming somewhat memory intensive, given the size of these data collections.
I would use an INNER JOIN query
SELECT *
FROM Items a
INNER JOIN Values b
ON a.id = b.itemID
INNER JOIN Propeties c
ON b.propID = c.id
WHERE c.title = 'height' AND b.value = '55'
Now in where you can place any of your column table, they are all joine now, just remember to preoend table alias (a,b,c) to your column name according
If you want to avoid joins you can create another table which will have three columns Item_Id, Property_Id and Value_Id. In this table you can search any thing on the basis of Id.
OR
You can do this:
SELECT * FROM Items WHERE IN (SELECT itemID FROM Values WHERE value=SOMEVALUE)
I have a set of tables and I am trying to get the two counts by state to display. It's proving to be a little tricky partly because some results will have a count of 0. I'm not sure how to deal with those at the moment.
First I'll show my table structure and then I'll explain what counts I'm trying to get. I'm thinking its probably something simple, but I'm a little rusty on sql queries.
Here is how my tables are setup. I have one primary table that I'm using to join the other tables too.
t1 (primary table)
ID, qrtID, sdID, published
t2
qID, qTypes, qSlug
t3
stateID, stateName, stateAbbr
The values link like this. t1.qrtID = t2.qID, t1.sdID = t3.stateID.
The qSlug values has 2 possible values (past and present), so i want to get the counts based on those groups.
What I want to end up with are columns for stateName, qSlug_count1, and qSlug_count2. If there is a count of "0", i want to display "0".
So for now this is what i got.
SELECT * FROM
(SELECT sdID, COUNT(qrtID) AS past_count FROM t1 WHERE qrtID = "1" GROUP BY sdID) c1
LEFT JOIN
(SELECT sdID, COUNT(qrtID) AS pres_count FROM t1 WHERE qrtID = "2" GROUP BY sdID) c2
ON c1.sdID = c2.sdID
The results from this query are close to what I need, but i am missing some data. I need to get the stateName, stateAbbr, and also if there is a count of 0, show a 0 in the column. So all states should be respresented in the results.
So, the question is how can i modify the query I have above to add in the additional tables and join them to correct values AND also be able to show zero values if there are no records that match?
Just use conditional aggregation in a single query:
SELECT sdID,
sum(qrtID = "1") AS past_count
sum(qrtID = "2") AS pres_count
FROM t1
GROUP BY sdID;
Your query is missing rows because some sdIDs have only 1's and others have only 2's. You might want to add:
where qrtID in ("1", "2")
if you don't want rows where two 0s could appear.
I have a query which goes like this:
SELECT insanlyBigTable.description_short,
insanlyBigTable.id AS insanlyBigTable,
insanlyBigTable.type AS insanlyBigTableLol,
catalogpartner.id AS catalogpartner_id
FROM insanlyBigTable
INNER JOIN smallerTable ON smallerTable.id = insanlyBigTable.catalog_id
INNER JOIN smallerTable1 ON smallerTable1.catalog_id = smallerTable.id
AND smallerTable1.buyer_id = 'xxx'
WHERE smallerTable1.cont = 'Y' AND insanlyBigTable.type IN ('111','222','33')
GROUP BY smallerTable.id;
Now, when I run the query first time it copies the giant table into a temp table... I want to know how I can prevent that? I am considering a nested query, or even to reverse the join (not sure the effect would be to run faster), but that is well, not nice. Any other suggestions?
To figure out how to optimize your query, we first have to boil down exactly what it is selecting so that we can preserve that information while we change things around.
What your query does
So, it looks like we need the following
The GROUP BY clause limits the results to at most one row per catalog_id
smallerTable1.cont = 'Y', insanelyBigTable.type IN ('111','222','33'), and buyer_id = 'xxx' appear to be the filters on the query.
And we want data from insanlyBigTable and ... catalogpartner? I would guess that catalogpartner is smallerTable1, due to the id of smallerTable being linked to the catalog_id of the other tables.
I'm not sure on what the purpose of including the buyer_id filter on the ON clause was for, but unless you tell me differently, I'll assume the fact it is on the ON clause is unimportant.
The point of the query
I am unsure about the intent of the query, based on that GROUP BY statement. You will obtain just one row per catalog_id in the insanelyBigTable, but you don't appear to care which row it is. Indeed, the fact that you can run this query at all is due to a special non-standard feature in MySQL that lets you SELECT columns that do not appear in the GROUP BY statement... however, you don't get to select WHICH columns. This means you could have information from 4 different rows for each of your selected items.
My best guess, based on column names, is that you are trying to bring back a list of items that are in the same catalog as something that was purchased by a given buyer, but without any more than one item per catalog. In addition, you want something to connect back to the purchased item in that catalog, via the catalogpartner table's id.
So, something probably akin to amazon's "You may like these items because you purchased these other items" feature.
The new query
We want 1 row per insanlyBigTable.catalog_id, based on which catalog_id exists in smallerTable1, after filtering.
SELECT
ibt.description_short,
ibt.id AS insanlyBigTable,
ibt.type AS insanlyBigTableLol,
(
SELECT smallerTable1.id FROM smallerTable1 st
WHERE st.buyer_id = 'xxx'
AND st.cont = 'Y'
AND st.catalog_id = ibt.catalog_id
LIMIT 1
) AS catalogpartner_id
FROM insanlyBigTable ibt
WHERE ibt.id IN (
SELECT (
SELECT ibt.id AS ibt_id
FROM insanlyBigTable ibt
WHERE ibt.catalog_id = sti.catalog_id
LIMIT 1
) AS ibt_id
FROM (
SELECT DISTINCT(catalog_id) FROM smallerTable1 st
WHERE st.buyer_id = 'xxx'
AND st.cont = 'Y'
AND EXISTS (
SELECT * FROM insanlyBigTable ibt
WHERE ibt.type IN ('111','222','33')
AND ibt.catalog_id = st.catalog_id
)
) AS sti
)
This query should generate the same result as your original query, but it breaks things down into smaller queries to avoid the use (and abuse) of the GROUP BY clause on the insanlyBigTable.
Give it a try and let me know if you run into problems.
I am brand new to SQL and am working with the following code provided to us by one of our vendors:
SELECT DISTINCT MriPatients.PatientID
INTO #UniquePt
FROM MriPatients
INNER JOIN #TotalPopulation ON MriPatients.PatientID = #TotalPopulation.PatientID
Set #TotalUniquePatients = (Select Count(*) FROM #UniquePt)
What happens is the Set line causes #TotalUniquePatients to be set to 0 even though there are many unique patient ids in our database. That value is then later used as a denominator in a division which causes a divide by 0 error.
Now it seems to me that this is easy to fix by using COUNT DISTINCT on the MriPatients table; then you don't need to create #UniquePt at all...this is the only place that table is used. But, I don't understand why the code as it is gets a 0 result when counting #UniquePt. If you remove the INNER JOIN, the Set returns a correct result...so what does the INNER JOIN do to #UniquePt?
If it matters, we are using SQL Server 2008.
The result is 0 because of 1 of 2 situations:
#TotalPopulation is empty
#TotalPopulation contains no records that have the same value for PatientID as the records in MriPatients
How are you populating #TotalPopulation?
A COUNT DISTINCT won't necessarily do the same thing. It depends on what you fill #TotalPopulation with. If all you want is the number of unique patients in MriPatients then yes, the COUNT DISTINCT will work. But if you're filling #TotalPopulation based on some kind of logic then they're the COUNT DISTINCT won't necessarily give you the same results as the COUNT of the joined tables.
The INNER JOIN causes you to insert ONLY records that have a matching PatientID in the #TotalPopulation table.
I'm guessing you don't, or that table isn't populated, which is causing the issue.
Is there a reason you are joining to it in the first place?