Got a task at my job to get several fields from different tables into one sheet, using SQL Developer. Im a noob to SQL, however managed to build something. Taking a look at my output learns me that the restrictions I built in do not work. Short description below. Can someone please help me?! In my output I still see values other than 1006 in the ATINN field, values other tham Empty in the BWTAR field.. What am I doing wrong?
5 tables linked together
Restriction on Users (DMSTRAATL, etc)
Restriction on Productgroup (006*, etc)
Restriction on some individual products
Restriction on product type (HERB, etc)
Restriction on specific data field (All products should have atinn = 1006)
Restiction on specific data field (all products should have bwtar = empty)
SELECT
dmssap.mara.matnr, dmssap.mara.mtart, dmssap.mara.matkl,
dmssap.mara.ersda, dmssap.mara.ernam, dmssap.mara.bismt,
dmssap.marc.werks, dmssap.inob.cuobj,
LPAD(INOB.CUOBJ, 18, '0') AS CUOBJ_18, dmssap.ZMM_MATNR_MPO.matnr, dmssap.ZMM_MATNR_MPO.pname,
dmssap.ZMM_MATNR_MPO.stat, dmssap.mbew.bwkey, dmssap.mbew.bklas,
dmssap.mbew.bwtar, dmssap.mbew.vprsv, dmssap.mbew.bwtty, dmssap.mbew.verpr,
dmssap.mbew.stprs, dmssap.ZMM_MATNR_MPO.matnr, dmssap.ZMM_MATNR_MPO.pname,
dmssap.ZMM_MATNR_MPO.stat, dmssap.ausp.atinn, dmssap.ausp.atwrt
FROM dmssap.mara
LEFT OUTER JOIN dmssap.marc
ON (dmssap.marc.matnr) = (dmssap.mara.matnr)
LEFT OUTER JOIN dmssap.ZMM_MATNR_MPO
ON (dmssap.ZMM_MATNR_MPO.matnr) = (dmssap.mara.matnr)
LEFT OUTER JOIN dmssap.mbew
ON CONCAT(dmssap.mbew.matnr, dmssap.mbew.bwkey) = CONCAT(dmssap.marc.matnr, dmssap.marc.werks)
LEFT OUTER JOIN dmssap.inob
ON (dmssap.inob.objek) = (dmssap.mara.matnr)
LEFT OUTER JOIN dmssap.ausp
ON dmssap.ausp.objek = LPAD(INOB.CUOBJ, 18, '0')
WHERE (dmssap.mara.ernam) IN (
'DMSTRAATL', 'V0342628', 'V0343809',
'V0336003', 'V0009830', 'V0309577', 'V0010144'
)
AND (dmssap.mara.matkl) IN (
'006*', '007120', '007130', '007140', '007170',
'007180', '007210', '007220', '007230',
'007250', '007270', '007280', '007290',
'007300', '007320', '007340',
'007370', '007380', '007400', '007420'
)
OR (dmssap.mara.matnr) IN (
'000000010001767697', '000000010001870117', '000000010001870116', '000000010001870115',
'000000010001870114', '000000010001870113', '000000010001870112'
)
AND (dmssap.mara.mtart) IN ('HERB', 'HALB', 'ZSTP')
AND (dmssap.ausp.atinn) = '1006'
AND (dmssap.mbew.bwtar) IS NULL;
AND operator has an higher precedence order than OR . to make your query easily readable use braces () around filter clauses.
Let's say you want to select records which have certain values in dmssap.mara.matkl or certain values in dmssap.mara.matnr then you can use braces between these blocks to be precise as shown below.
AND (
(dmssap.mara.matkl) IN (
'006*', '007120', '007130', '007140', '007170',
'007180', '007210', '007220', '007230',
'007250', '007270', '007280', '007290',
'007300', '007320', '007340',
'007370', '007380', '007400', '007420'
)
OR (dmssap.mara.matnr) IN (
'000000010001767697', '000000010001870117', '000000010001870116', '000000010001870115',
'000000010001870114', '000000010001870113', '000000010001870112'
)
)
WHERE (dmssap.mara.ernam) IN (
'DMSTRAATL', 'V0342628', 'V0343809',
'V0336003', 'V0009830', 'V0309577', 'V0010144'
)
AND (dmssap.mara.matkl) IN (
'006*', '007120', '007130', '007140', '007170',
'007180', '007210', '007220', '007230',
'007250', '007270', '007280', '007290',
'007300', '007320', '007340',
'007370', '007380', '007400', '007420'
)
OR (dmssap.mara.matnr) IN (
'000000010001767697', '000000010001870117', '000000010001870116', '000000010001870115',
'000000010001870114', '000000010001870113', '000000010001870112'
)
AND (dmssap.mara.mtart) IN ('HERB', 'HALB', 'ZSTP')
AND (dmssap.ausp.atinn) = '1006'
AND (dmssap.mbew.bwtar) IS NULL;
The crux is in your WHERE statement. The evaluation order for keywords in the WHERE statement is NOT -> AND -> OR
What you seem to want is this instead:
WHERE (dmssap.mara.ernam) IN (
'DMSTRAATL', 'V0342628', 'V0343809',
'V0336003', 'V0009830', 'V0309577', 'V0010144'
)
AND (dmssap.mara.matkl) IN ((
'006*', '007120', '007130', '007140', '007170',
'007180', '007210', '007220', '007230',
'007250', '007270', '007280', '007290',
'007300', '007320', '007340',
'007370', '007380', '007400', '007420'
)
OR (dmssap.mara.matnr) IN (
'000000010001767697', '000000010001870117', '000000010001870116', '000000010001870115',
'000000010001870114', '000000010001870113', '000000010001870112'
))
AND (dmssap.mara.mtart) IN ('HERB', 'HALB', 'ZSTP')
AND (dmssap.ausp.atinn) = '1006'
AND (dmssap.mbew.bwtar) IS NULL;
Notice the two extra brackets around the OR on the AND
Related
Having this simple group of tables, I would like to make an inventory discriminating equal products that came from different providers, but I'm getting an "ambiguity error" running a query I though it would work. I don't know how to solve this.
Here's the query I tried:
SELECT tblProducts.product_Name,
tblProviders.provider,
Nz(Sum(tblIntakes.intake_QTY),0)-
Nz(Sum(tblExits.exit_QTY)) AS Stock
FROM tblProviders,
(tblProducts LEFT JOIN
tblExits
ON tblProducts.product_ID = tblExits.product_ID
) LEFT JOIN
tblIntakes
ON tblProducts.product_ID = tblIntakes.product_ID
GROUP BY tblProducts.product_Name, tblProviders.provider;
You may use subqueries in this case:
SELECT
tblProducts.product_Name,
tblProviders.provider,
Nz((
SELECT SUM(intake_QTY)
FROM tblIntakes
WHERE
tblIntakes.product_ID = tblProducts.product_ID AND
tblIntakes.provider_ID = tblProviders.provider_ID
), 0) -
Nz((
SELECT SUM(exit_QTY)
FROM tblExits
WHERE
tblExits.product_ID = tblProducts.product_ID AND
tblExits.provider_ID = tblProviders.provider_ID
), 0) AS Stock
FROM tblProviders, tblProducts;
I'm having a problem with a query in postgres, the table cgporders_items has a field called return, I cannot get actual result of that field with this query, it returns me al ceros.
SELECT "Cgporder".id AS "Cgporder__id"
,"Sale".preorder_number AS "Sale__preorder_number"
,"Contact".id AS "Contact__id"
,"Contact".NAME AS "Contact__name"
,"Ptype".NAME AS "Ptype__name"
,(
SELECT code
FROM products
WHERE id = "CgporderItem".parent_id
) AS "Product__parent_code"
,"Product".id AS "Product__id"
,"Product".code AS "Product__code"
,"Product".NAME AS "Product__name"
,"CgporderItem".quantity AS "CgporderItem__quantity"
,"CgporderItem".return AS "CgporderItem__return"
,"CgporderItem".cep_id AS "CgporderItem__cep"
FROM cgporders AS "Cgporder"
INNER JOIN contacts AS "Contact" ON ("Contact".id = "Cgporder".contact_id)
INNER JOIN cgporders_items AS "CgporderItem" ON ("Cgporder".id = "CgporderItem".cgporder_id)
INNER JOIN products AS "Product" ON ("Product".id = "CgporderItem".product_id)
INNER JOIN ptypes AS "Ptype" ON ("Ptype".id = "Product".ptype_id)
LEFT JOIN cgporders_sales AS "CgporderSale" ON ("Cgporder".id = "CgporderSale".cgporder_id)
LEFT JOIN sales AS "Sale" ON ("Sale".id = "CgporderSale".sale_id)
WHERE "CgporderItem".parent_id != 0
AND "Cgporder"."issue_date" >= '2015-11-27'
AND "Cgporder"."issue_date" <= '2015-11-27'
AND "Cgporder"."status" = 'confirmed'
ORDER BY "Ptype".NAME
,"Product"."code";
There are actually a lots of rows that matches the select condition, but it return cero on "CgporderItem".return AS "CgporderItem__return"
If I make a simple query like select "return" from cgporders_items it works. But in this query it does not work.
Can you help me please?
"return" is a reserved word in SQL, but not in Postgres. See the list here. The following code works find in Postgres (SQL Fiddle is here):
create table dum (return int);
select dum.return from dum;
Your problem is something else. If I had to guess, the where clause is too restrictive (the condition on dates is a bit suspect).
I have three tables that need to be joined in order to get monthly inventory data in return.
Table 1: TargetInventory
Table 2: TargetValue
Table 3: TargetWeight
[TargetInventory] does not change after being added the first time.
[TargetValue] is just a small table that includes prices of various types of metal.
[TargetWeight] is updated monthly as part of our inventory process. We INSERT new data, we never UPDATE old data.
Below is the relationship between these tables. (Sorry, I don't have the reputation points to post an image. Brand new here, so hopefully this makes sense.)
(* = UniqueKey)
--TargetValue-- --TargetInventory-- --TargetWeight--
*MaterialID <===| *TargetID <=====| *ID
Material |===> MaterialID |===> TargetID
PricePerOunce Length RecordDate
Density Width Weight
Thickness
DateInInventory
The TargetWeight table contains multiple records for TargetID (since a new one is added every month at inventory). That's good for me to track historical usage, but for the current inventory value, I only need the most recent TargetWeight.Weight to be returned.
I don't know how to do a CROSS APPLY from within another INNER JOIN, so I'm at a loss for how to do this (without switching to mySQL and just doing a LIMIT 1...)
I think it needs to look something like what's below, but I'm not sure how to finish the query.
SELECT
TargetInventory.TargetID AS TargetInventory_TargetID,
TargetInventory.MaterialID AS TargetInventory_MaterialID,
TargetInventory.Length,
TargetInventory.Width,
TargetInventory.Thickness,
TargetValue.MaterialID AS TargetValue_MaterialID,
TargetValue.PricePerOunce,
TargetValue.Density,
TargetWeight.ID,
TargetWeight.TargetID AS TargetWeight_TargetID,
TargetWeight.RecordDate,
TargetWeight.Weight
FROM
(TargetValue
INNER JOIN TargetInventory
ON TargetValue.[MaterialID] = TargetInventory.[MaterialID]
)
CROSS APPLY (
SELECT TOP 1 *
FROM .....
)
The following query works for me in Access 2010. It uses an INNER JOIN on a subquery to take the place of the CROSS APPLY (which Access SQL doesn't support). It assumes that there will be no more than one [TargetWeight] record for a given (TargetID, RecordDate):
SELECT
TargetInventory.TargetID AS TargetInventory_TargetID,
TargetInventory.MaterialID AS TargetInventory_MaterialID,
TargetInventory.Length,
TargetInventory.Width,
TargetInventory.Thickness,
TargetValue.MaterialID AS TargetValue_MaterialID,
TargetValue.PricePerOunce,
TargetValue.Density,
LatestWeight.ID,
LatestWeight.TargetID AS TargetWeight_TargetID,
LatestWeight.RecordDate,
LatestWeight.Weight
FROM
(
TargetValue
INNER JOIN
TargetInventory
ON TargetValue.[MaterialID] = TargetInventory.[MaterialID]
)
INNER JOIN
(
SELECT tw.*
FROM
TargetWeight AS tw
INNER JOIN
(
SELECT TargetID, MAX(RecordDate) AS LatestDate
FROM TargetWeight
GROUP BY TargetID
) AS latest
ON latest.TargetID=tw.TargetID
AND latest.LatestDate=tw.RecordDate
) AS LatestWeight
ON LatestWeight.TargetID = TargetInventory.TargetID
Alternative approach specifically for Access 2010 or later
If the above query bogs down with a large number of rows in [TargetWeight] then another possible solution for Access 2010+ would be to add a Yes/No field named [Current] to the [TargetWeight] table and use the following After Insert data macro to ensure that only the latest record for each [TargetID] is flagged as [Current]:
Once that is done, the query would simply be
SELECT
TargetInventory.TargetID AS TargetInventory_TargetID,
TargetInventory.MaterialID AS TargetInventory_MaterialID,
TargetInventory.Length,
TargetInventory.Width,
TargetInventory.Thickness,
TargetValue.MaterialID AS TargetValue_MaterialID,
TargetValue.PricePerOunce,
TargetValue.Density,
TargetWeight.ID,
TargetWeight.TargetID AS TargetWeight_TargetID,
TargetWeight.RecordDate,
TargetWeight.Weight
FROM
(
TargetValue
INNER JOIN
TargetInventory
ON TargetValue.[MaterialID] = TargetInventory.[MaterialID]
)
INNER JOIN
TargetWeight
ON TargetInventory.TargetID = TargetWeight.TargetID
WHERE TargetWeight.Current = True;
To maximize performance, the [TargetWeight].[TargetID] and [TargetWeight].[Current] fields should be indexed.
SELECT TargetInventory.TargetID AS TargetInventory_TargetID,
TargetInventory.MaterialID AS TargetInventory_MaterialID,
TargetInventory.Length,
TargetInventory.Width,
TargetInventory.Thickness,
TargetValue.MaterialID AS TargetValue_MaterialID,
TargetValue.PricePerOunce,
TargetValue.Density, Weight.ID,
Weight.TargetID AS TargetWeight_TargetID,
Weight.RecordDate,
Weight.Weight
FROM TargetInventory
INNER JOIN TargetValue ON TargetValue.[MaterialID] = TargetInventory.[MaterialID]
CROSS APPLY (
SELECT TOP 1 *
FROM TargetWeight
WHERE TargetID = TargetInventory.TargetID
ORDER BY RecordDate DESC
) AS Weight
I`m working on some sql queries to get some data out of a table; I have made 2 queries for the
same data but both give another result. The 2 queries are:
SELECT Samples.Sample,
data_overview.Sample_Name,
data_overview.Sample_Group,
data_overview.NorTum,
data_overview.Sample_Plate,
data_overview.Sentrix_ID,
data_overview.Sentrix_Position,
data_overview.HybNR,
data_overview.Pool_ID
FROM tissue INNER JOIN (
( patient INNER JOIN data_overview
ON patient.Sample = data_overview.Sample)
INNER JOIN Samples ON
(data_overview.Sample_id = Samples.Sample_id) AND
(patient.Sample = Samples.Sample)
) ON
(tissue.Sample_Name = data_overview.Sample_Name) AND
(tissue.Sample_Name = patient.Sample_Name)
WHERE data_overview.Sentrix_ID= 1416198
OR data_overview.Pool_ID='GS0005701-OPA'
OR data_overview.Pool_ID='GS0005702-OPA'
OR data_overview.Pool_ID='GS0005703-OPA'
OR data_overview.Pool_ID='GS0005704-OPA'
OR data_overview.Sentrix_ID= 1280307
ORDER BY Samples.Sample;")
And the other is
SELECT Samples.Sample,
data_overview.Sample_Name,
data_overview.Sample_Group,
data_overview.NorTum,
data_overview.Sample_Plate,
data_overview.Sentrix_ID,
data_overview.Sentrix_Position,
data_overview.HybNR,
data_overview.Pool_ID
FROM tissue INNER JOIN
(
(patient INNER JOIN data_overview
ON patient.Sample = data_overview.Sample)
INNER JOIN Samples ON
(data_overview.Sample_id = Samples.Sample_id)
AND (patient.Sample = Samples.Sample)) ON
(tissue.Sample_Name = data_overview.Sample_Name)
AND (tissue.Sample_Name = patient.Sample_Name)
WHERE ((
(data_overview.Sentrix_ID)=1280307)
AND (
(data_overview.Pool_ID)="GS0005701-OPA"
OR (data_overview.Pool_ID)="GS0005702-OPA"
OR (data_overview.Pool_ID)="GS0005703-OPA"
OR (data_overview.Pool_ID)="GS0005704-OPA"))
OR (((data_overview.Sentrix_ID)=1416198))
ORDER BY data_overview.Sample;
The one in the top is working quite well but it still won't filter the sentrix_ID.
The second 1 is created with Access but when I try to run this Query in R it gave
a unexpected symbol error. So if anyone knows how to create a query that filter POOL_ID and Sentrix_id with the given parameters thanks in advance
Is it a case of making the where clause something like this:
WHERE Sentrix_ID = 1280307 AND (Pool_ID = 'VAL1' OR Pool_ID = 'VAL2' OR Pool_ID = 'VAL3')
i.e. making sure you have brackets around the "OR" components?
Maybe you meant:
...
WHERE data_overview.Sentrix_ID IN (1280307,1416198 )
AND data_overview.Pool_ID IN ("GS0005701-OPA", "GS0005702-OPA", "GS0005703-OPA" ,"GS0005704-OPA")
;
In access I wrote this query:
Select
I.sysid, I.MemberNumber, I.Date, I.Distributer,
F.MemberNumber as FMember, F.Date as FDate, I.Distributer as FDistributer
From Initial as I
Left Join Final as F ON
I.MemberNumber=F.MemberNumber and
I.Distributer=F.Distributer and
I.Date>=F.Date-14 and
I.Date<=F.Date+14;
But the left join is not behavior properly. There are fewer rows in this table then there are in Initial... but it should be keeping ALL rows from initial, because I am using a left join, right? I have found several rows in initial (like sysid=7, which is Initial's key) that just isn't coming into this table.
It may have to do with your AND logic. Add some ( ) parenthesis to this to include it all like so:
Select
I.sysid, I.MemberNumber, I.Date, I.Distributer,
F.MemberNumber as FMember, F.Date as FDate, I.Distributer as FDistributer
From Initial as I
Left Join Final as F ON
(I.MemberNumber=F.MemberNumber and
I.Distributer=F.Distributer and
(I.Date>=F.Date-14) and
(I.Date<=F.Date+14));
Also I think there is a dateadd function, I'd use that instead of + / -.
If you're in the Query Designer, make sure all the filters are cleared. I've built your tables and sql and can't reproduce your error.
SELECT I.sysid
, I.MemberNumber
, I.Dated
, I.Distributer
, F.MemberNumber
, F.Dated AS FDated
, F.Distributer AS FDistributer
FROM Initial AS I
LEFT JOIN Final AS F
ON I.Distributer = F.Distributer
AND I.MemberNumber = F.MemberNumber
AND I.Dated>=F.Dated-14
AND I.Dated<=F.Dated+14;
Try adding additional fields to the original table and using update queries to add extra columns. This way you can be sure you won't drop any columns.