I have a table that includes a JSON. I want to get a certain parameter of the JSON and remove the € sign out of this JSON (so I get a numeric value that I can sum).
That's the base query that works:
With C as (
SELECT A.identifier,
JSON_VALUE(A.jsonBody,'$.path) as somethingA,
JSON_VALUE(A.jsonBody,'$.path) as somethingB
FROM table A WITH(NOLOCK)
join table B on (A.identifier = B.identifier)
WHERE A.statement = 'x')
select C.identifier,
replace (C.fieldA, '€','') as TotalA,
replace (C.fieldB, '€','') as TotalB
from C)
Unfortunately I am now stuck as I want to get the sum of TotalA per identifier.
As described my query works but I want to get the sum per identifier. So I thought I'd be an idea to simply create (create xxx as (query)) but I get an error.
Anyone has an idea on
how I can improve this query in general (replace + JSON_Value in one commmand?)
how I can get the TotalA, TotalB amount per identifier?
Related
I have an issue where to create a report, I need two tables to join that don't have any way to join. I did find a way they could potentially join, but it's complicated.
There is table A, which contains a column called select_criteria. Here are some examples of 3 values it contains:
SELECT DISTINCT SUM(TRANSCRIPTDETAIL.CREDIT_BILLING) FROM SOMETABLE WHERE (( STUDENTFINANCIAL.TUITION_EXEMPTION = 'EMPFT' ) OR ( STUDENTFINANCIAL.TUITION_EXEMPTION = 'EMPPT' )))
SELECT DISTINCT SUM(TRANSCRIPTDETAIL.CREDIT_BILLING) FROM SOMETABLE WHERE ( STUDENTFINANCIAL.TUITION_EXEMPTION = 'PART50' )
In table B, I have a column called tuition_exemption, which contains values like:
EMPFT
EMPPT
PART50
At the tail end of the whole value within the column in table A, there are the tuition exemption codes that match the values in table B.
Is there a way using MSSQL where I can parse out the codes from the long statement in select_criteria, so that they perfectly match the codes from table B? This is my thought on a way to join up table A and table B like I need to do. The other complication is that there is a 1:many connection between select_criteria and a tuition_exemption value, but a 1:1 connection between a tuition_exemption value and a select_criteria value.
So in the end, the join between the two tables should print, in one example, the same select_criteria value twice (I am referencing the first value in my list above from table A), but in those two rows, the two different tuition_exemption values (EMPFT and EMPPT). Or in the case of table A example 2, it would be printed once and match up to PART50 once.
I am stuck here. I have a statement that successfully grabs the select_criteria values I want:
SELECT select_criteria
WHERE (
select_criteria LIKE '%EMPFT%' OR
select_criteria LIKE '%EMPPT%' OR
select_criteria LIKE '%PART50%' OR
)
But what I need to do is this. When it grabs the select_criteria values I want, I then want to print to a new column in this table the code it matches up to. Those codes are values in table B like 'EMPFT', 'EMPPT' and 'PART50'. That is why I was thinking of basically parsing out the codes from select_criteria, and printing them into the new column in table A. That way table A and table B have a value to match up on and I write run my report. I just don't now how to do it in SQL. I kind of know in Perl, but was hoping to just do all of this in SSMS 2012.
Thanks for any help!
byobob
You can use any expression which returns a boolean as a join criteria. Since LIKE returns a bool, you should be able to just do this:
select *
from tableA
join tableB
on tableA.select_criteria like '%' + tableB.codecolumn + '%'
I get the following error message
"Your query does not include the specified expression 'SampleCode' as part of an aggregate function."
I've looked into aggregate functions and have tried various ways to GROUP BY using the individual data fields that make up the code but I can't seem to get anything to work.
'SampleCode' is a concatenated query field (query name: datqry_SampleNumber) that is based on data from 3 different tables to create a unique value as follows...
SampleCode: IIf([tbl_Carcass.SampleNumber]="-999","-999",
"NPT-" & [tbl_SurveyInfo.SurveyYear*] & "-" &
[datqry_TransectData.Project_Code] & "-" & [tbl_Carcass.SampleNumber])
for SampleNumber values > 0001 (-999 is a placeholder indicating no SampleNumber assigned). Note, SurveyYear* is a calculated field based on the SurveyDate data field.
So, since SampleCode needs to be unique to each sample, I am trying to build a duplicate query, based on the aforementioned query, to identify duplicate SampleCodes so they can be relabeled and archived w/ a unique qualifier. The criteria for the duplicate query operation is as follows
In (SELECT [SampleCode] FROM [datqry_SampleNumber] As Tmp
GROUP BY [SampleCode] HAVING Count(*)>1 )
Any ideas on how to tackle this problem? Thank you in advance for your help and suggestions.
This looks like it might be a limitation of the JET engine used by Access to interpret its SQL.
It appears to be having trouble working with the subquery because it contains an aggregation of a calculated field (SampleCode in your case).
Try saving this as a separate query called, e.g. qryDuplicates:
SELECT [SampleCode] FROM [datqry_SampleNumber]
GROUP BY [SampleCode] HAVING Count(*)>1;
Then what you are trying to do will work as expected:
SELECT * from someTable WHERE someField IN (
SELECT * FROM qryDuplicates
);
TECHNICAL NOTE: I've tested it out and it is indeed specific to the fact that SampleCode is a calculated field. Doing exactly the same kind of grouped subquery works as expected when the field in question is not calculated.
With this test database this query works:
SELECT * FROM Table2 WHERE Field3 IN (
SELECT Field1 FROM datqry_SampleNumber
GROUP BY Field1 HAVING COUNT(*) > 1
);
And this doesn't
SELECT * FROM Table2 WHERE Field3 IN (
SELECT SampleCode FROM datqry_SampleNumber
GROUP BY SampleCode HAVING COUNT(*) > 1
);
This really isn't that complicated but I can't wrap my head around it. Ive searched thoroughly but even coming up with a search string or title for this question was hard enough. The explanation will tell all:
Table "labelDrops" has fields "PO" and "Qty" (among other unrelated fields)
Table "imageLiveCount" has field "PO"
I want to count instances (count(imageLiveCount.id)) where imageLiveCoount.PO = labelDrops.PO and then subtract that from the "QTY" to create a calculated field called "QtyLeft".
The result would basically look like "SELECT PO, Qty, answerToThisQuestion AS QtyLeft FROM labelDrops"
Start by creating a query which gives you the count for each PO in your imageLiveCount table:
SELECT i.PO, Count(*) AS CountOfInstances
FROM imageLiveCount AS i
GROUP BY i.PO
If that query returns what you want, join it to the labelDrops table and compute QtyLeft:
SELECT
l.PO,
l.Qty,
(l.Qty - sub.CountOfInstances) AS QtyLeft
FROM
labelDrops AS l
INNER JOIN
(
SELECT i.PO, Count(*) AS CountOfInstances
FROM imageLiveCount AS i
GROUP BY i.PO
) AS sub
ON l.PO = sub.PO
I have to compare comma separated values with a column in the table and find out which values are not in database. [kind of master data validation]. Please have a look at the sample data below:
table data in database:
id name
1 abc
2 def
3 ghi
SQL part :
Here i am getting comma separated list like ('abc','def','ghi','xyz').
now xyz is invalid value, so i want to take that value and return it as output saying "invalid value".
It is possible if i split those value, take it in temp table, loop through each value and compare one by one.
but is there any other optimal way to do this ??
I'm sure if I got the question right, however, I would personally be trying to get to something like this:
SELECT
D.id,
CASE
WHEN B.Name IS NULL THEN D.name
ELSE "invalid value"
END
FROM
data AS D
INNER JOIN badNames B ON b.Name = d.Name
--as SQL is case insensitive, equal sign should work
There is one table with bad names or invalid values if You prefer. This can a temporary table as well - depending on usage (a black-listed words should be a table, ad hoc invalid values provided by a service should be temp table, etc.).
NOTE: The select above can be nested in a view, so the data remain as they were, yet you gain the correctness information. Otherwise I would create a cursor inside a function that would go through the select like the one above and alter the original data, if that is the goal...
It sounds like you just need a NOT EXISTS / LEFT JOIN, as in:
SELECT tmp.InvalidValue
FROM dbo.HopeThisIsNotAWhileBasedSplit(#CSVlist) tmp
WHERE NOT EXISTS (
SELECT *
FROM dbo.Table tbl
WHERE tbl.Field = tmp.InvalidValue
);
Of course, depending on the size of the CSV list coming in, the number of rows in the table you are checking, and the style of splitter you are using, it might be better to dump the CSV to a temp table first (as you mentioned doing in the question).
Try following query:
SELECT SplitedValues.name,
CASE WHEN YourTable.Id IS NULL THEN 'invalid value' ELSE NULL END AS Result
FROM SplitedValues
LEFT JOIN yourTable ON SplitedValues.name = YourTable.name
Let's say that we have a table named Data with Id and Weather columns. Other columns in that table are not important to this problem. The Weather column can be null.
I want to display all rows where Weather fits a condition, but if there is a null value in weather then display null value.
My SQL so far:
SELECT *
FROM Data d
WHERE (d.Weather LIKE '%'+COALESCE(NULLIF('',''),'sunny')+'%' OR d.Weather IS NULL)
My results are wrong, because that statement also shows values where Weather is null if condition is not correct (let's say that users mistyped wrong).
I found similar topic, but there I do not find appropriate answer.
SQL WHERE clause not returning rows when field has NULL value
Please help me out.
Your query is correct for the general task of treating NULLs as a match. If you wish to suppress NULLs when there are no other results, you can add an AND EXISTS ... condition to your query, like this:
SELECT *
FROM Data d
WHERE d.Weather LIKE '%'+COALESCE(NULLIF('',''),'sunny')+'%'
OR (d.Weather IS NULL AND EXISTS (SELECT * FROM Data dd WHERE dd.Weather LIKE '%'+COALESCE(NULLIF('',''),'sunny')+'%'))
The additional condition ensures that NULLs are treated as matches only if other matching records exist.
You can also use a common table expression to avoid duplicating the query, like this:
WITH cte (id, weather) AS
(
SELECT *
FROM Data d
WHERE d.Weather LIKE '%'+COALESCE(NULLIF('',''),'sunny')+'%'
)
SELECT * FROM cte
UNION ALL
SELECT * FROM Data WHERE weather is NULL AND EXISTS (SELECT * FROM cte)
statement show also values where Wether is null if condition is not correct (let say that users typed wrong sunny).
This suggests that the constant 'sunny' is coming from end-user's input. If that is the case, you need to parameterize your query to avoid SQL injection attacks.