SQL SERVER SELECT sum values - sql

Problem is when I try get sum values from 2 different tables, but using condition from table 3 result are corrupted by wrong sum result . So I tried Select sum() as t1 (select sum()...) as t2 and I want to sum t1 and t2, in this way t1 and t2 result are correct
so there are code
SELECT
SUM(daa.[price]) AS t1,
(
SELECT SUM(dap.[price]) AS suma
FROM fydtr.dbo.[sales] AS dap,
[fydtr].[dbo].[work info] AS di
WHERE YEAR(di.[end of work datetime]) = 2013
AND MONTH(di.[end of work datetime]) = 12
AND di.[state] = 'e'
AND di.[reg. nr.] = dap.[reg. nr.]
) AS t2
FROM [fydtr].[dbo].[work sale] AS daa,
fydtr.dbo.[work info] AS dbi
WHERE YEAR(dbi.[end of work datetime]) = 2013
AND MONTH(dbi.[end of work datetime]) = 12
AND dbi.[state] = 'e'
AND dbi.[reg. nr.] = daa.[reg. nr.]
It gives result
t1 340
t2 509
And I need sum these and get 849 as t3.

What about something like this.
select t1, t2, t1 + t2 t3
from (
the query from your question
) temp

Not completely clear, due to missing input data. But I assume you're searching for something like this:
select sum(sale.pice) as t1
, sum(sales.price) as t2
, sum(sales.price) + sum(sale.price) as t3
from [work info] as info
left outer join [work sale] as sale on (info.state = 'e' and info.[reg. nr.] = sale.[reg. nr.])
left outer join [work sales] as sales on (info.state = 'e' and info.[reg. nr.] = sales.[reg. nr.])
where year(info.[end of work datetime]) = 2013
and month(info.[end of work datetime]) = 12
This depends on the relations between your tables, e.g. in my example, I'm assuming that there's only one entry per [reg. nr.] in all tables. Otherwise you could use "window functions", or UNIONS or CTE's (http://msdn.microsoft.com/en-us/library/ms175972.aspx). You might need to supply more context to get the answer you're searching for.
My given query is probably a little bit cleaner than your query. If that's not an issue, or if my assumption is wrong, then Dan Bracuk's answer helps you out.
And you should probably look at the column names, too. They're a little bit too complex in my opinion :)

Related

Oracle SQL Developer - error when referencing fields within nested from statements

For the below query I am getting an error with line 4 when referencing variables within "y". The query runs successfully when I use just " y.* " (line 5), however it generates an error when I try to also pull from the specified fields in line 4 (y.field1 as PRODUCT, y.field2 as PRODUCT_TYPE, y.entity, y.TYPE1). For the output, I want these fields listed first for visual reference.
I have this approach/ logic working for other queries (as i'm re using this logic for multiple variations of queries and various tables). However, I think that the issue with this one lies in my attempt to reference fields from tables that are in my join statements.
(
select
-- categorization fields:
-- table2.field1 as PRODUCT, table2.field2 as PRODUCT_TYPE, table3.entity, table3.TYPE1
y.field1 as PRODUCT,
y.field2 as PRODUCT_TYPE,
y.entity,
y.TYPE1
,y.*
from (
select *
from (
-- table references:
select table1.*,
row_number() over (
partition by
-- categorization fields:
table2.field1,
table2.field2,
table3.entity,
table3.TYPE1
order by table3.entity
) as rn
-- table references
from table1
-- joins, links, and filtering:
inner join table6 on table1.field_1 = table6.code1
inner join table5 on (table6.code = table5.code1)
AND (table6.code = table5.code)
left join table3 on table6.ent1 = table3.ent_code
left join table2 on table1.extid = table2.extID
where table1.tdate between '01-APR-19' and '01-APR-21'
AND table1.refe NOT IN ('OFF')
) x
-- sample rows:
where rn <= 2
) y
);
Let me know if anyone has a way that I can maybe better specify which tables those fields come from. I wish I could just do something like this:
y.table2.field1 as PRODUCT,
y.table2.field2 as PRODUCT_TYPE,
y.table3.entity,
y.table3.TYPE1
Sorry that I don't have a fiddle available!
Let me know if anyone has a way that I can maybe better specify which tables those fields come from.
Don't use select *. Instead, use the column names and give them appropriate aliases so you know where they came from:
As an example:
SELECT small_value,
medium_value,
big_value
FROM (
SELECT small.value AS small_value,
medium.value AS medium_value,
big.value AS big_value
FROM big
CROSS JOIN medium
CROSS JOIN small
)
WHERE 1 = 1
In your query, instead of using SELECT * in y or using SELECT table1.* in x you can name the columns and give them descriptive aliases.
I am getting an error with line 4 when referencing variables within "y".
(
select
-- categorization fields:
-- table2.field1 as PRODUCT, table2.field2 as PRODUCT_TYPE, table3.entity, table3.TYPE1
That is because you cannot see TABLE2 or TABLE3 because the only "view" you are looking at is of the sub-query with the alias y.
If you want to see those columns then you need to SELECT them inside the x subquery and pass them to each subsequent outer-query.
(
select *
from (
-- table references:
select table1.field1 AS t1_product,
table1.field2 AS t1_product_type,
table1.entity AS t1_entity,
table1.type1 AS t1_type1,
table2.field1 AS t2_product,
table2.field2 AS t2_product_type,
table2.entity AS t2_entity,
table2.type1 AS t2_type1,
table3.field1 AS t3_product,
table3.field2 AS t3_product_type,
table3.entity AS t3_entity,
table3.type1 AS t3_type1,
row_number() over (
partition by
-- categorization fields:
table2.field1,
table2.field2,
table3.entity,
table3.TYPE1
order by table3.entity
) as rn
-- table references
from table1
-- joins, links, and filtering:
inner join table6 on table1.field_1 = table6.code1
inner join table5 on (table6.code = table5.code1)
AND (table6.code = table5.code)
left join table3 on table6.ent1 = table3.ent_code
left join table2 on table1.extid = table2.extID
where table1.tdate between '01-APR-19' and '01-APR-21'
AND table1.refe NOT IN ('OFF')
) x
-- sample rows:
where rn <= 2
);

Check if a combination of fields already exists in the table

My weakest area of SQL are self JOINS, currently struggling with an issue.
I need to find the latest entry in a table, I'm using a WHERE DATEFIELD IN (SELECT MAX(DATEFIELD) FROM TABLE) to do this. I then need to establish if 3 columns from that already exist in the same TABLE.
My latest attempt looks like this -
SELECT * FROM PART_TABLE
WHERE NOT EXISTS
(
SELECT
t1.DATEFIELD
t1.CODE1
t1.CODE2
t1.CODE3
FROM PART_TABLE t1
INNER JOIN PART_TABLE t2 ON t1.UNIQUE = t2.UNQIUE
)
WHERE t1.DATEFIELD IN
(
SELECT MAX(DATEFIELD)
FROM PARTTABLE
)
)
I think part of the issue is that I can't exclude the unique row from t1 when checking in t2 using this method.
Using MSSQL 2014.
The following query will return the latest record from your table and a bit flag whether a duplicate tuple {Code1, Code2, Code3} exists in it under a different identifier:
select top (1) p.*,
case when exists (
select 0 from dbo.Part_Table t where t.Unique != p.Unique
and t.Code1 = p.Code1 and t.Code2 = p.Code2 and t.Code3 = p.Code3
) then 1
else 0 end as [IsDuplicateExists]
from dbo.Part_Table p
order by p.DateField desc;
You can use this example as a template to address your specific needs, which unfortunately aren't immediately apparent from your explanation.

How to join 100 random rows from table 1 multiple other tables in oracle

I have scrapped my previous question as I did not do a good job explaining. Maybe this will be simpler.
I have the following query.
Select * from comp_eval_hdr, comp_eval_pi_xref, core_pi, comp_eval_dtl
where comp_eval_hdr.START_DATE between TO_DATE('01-JAN-16' , 'DD-MON-YY')
and TO_DATE('12-DEC-17' , 'DD-MON-YY')
and comp_eval_hdr.COMP_EVAL_ID = comp_eval_dtl.COMP_EVAL_ID
and comp_eval_hdr.COMP_EVAL_ID = comp_eval_pi_xref.COMP_EVAL_ID
and core_pi.PI_ID = comp_eval_pi_xref.PI_ID
and core_pi.PROGRAM_CODE = 'PS'
Now if I only want a random 100 rows from the comp_eval_hdr table to join with the other tables how would I go about it? If it makes it easier you can disregard the comp_eval_dtl table.
I think you are pretty much there. You just need subqueries, table aliases, and JOIN conditions:
SELECT . . .
FROM (SELECT a.*
FROM (SELECT a.*
FROM a
WHERE a.START_DATE BEWTWEEN DATE '2016-01-01' AND DATE '2017-12-12'
ORDER BY DBMS_RANDOM.VALUE
) a
WHERE ROWNUM <= 100
) a JOIN
mapping m
ON a.? = m.? JOIN
b
ON m.? = b.?;
The ? is just a placeholder for the join columns.
It's a bit of a stretch to know what you want with the question as written but here's my attempt.
WITH rand_list AS
(SELECT * FROM comp_eval_hdr
WHERE comp_eval_hdr.START_DATE BEWTWEEN TO_DATE('01-JAN-16' , 'DD-MON-YY') AND TO_DATE('12-DEC-17' , 'DD-MON-YY')
ORDER BY DBMS_RANDOM.VALUE)
first_100 AS
(SELECT *
FROM rand_list
WHERE ROWNUM <=100)
SELECT md.col_1, t3.col_a
FROM first_100 md
INNER JOIN
table2 t2 ON md.id_column = t2.fk_comp_eval_hdr_id
INNER JOIN
table3 t3 ON t3.id_column = t2.fk_table3_id
You haven't given any indication how they join or the table names and obviously I haven't run this against any mock tables.
You've got a list of randomised records with RAND_LIST which you could, if you wanted, combine with the FIRST_100 query (your choice).
The main query then just joins that through your mapping table (T2) to your 'multiples' table (T3).
how does table 2 look like?...Let me put one example as person table and order table?
select * from (
select * from person ps , order order where ps.city = 'mumbai' and ps.id = order.purchasedby ) porder where porder.rownum <= 100
I did not tested it but it will look something like this.

How to convert SUBSELECT with TOP and ORDER BY to JOIN

I have a working sql select, which looks like this
[Edited: Im sorry i did one mistake in the question, i edited alias of Table1 but im trying the answers]
SELECT
m.Column1
,t2.Column2
,COALESCE
(
(
SELECT TOP 1 Vat
FROM LinkedDBServer.DatabaseName.dbo.TableName t3
WHERE
m.MaterialNumber = t3.MaterialNumber COLLATE Czech_CI_AS
and t3.Currency = …
and ...
ORDER BY [Date] DESC
), m.Vat
) as Vat
FROM Table1 m
JOIN Table2 t2 on (m.Column1 = t2.Column1)
It works but the problem is that it takes too long and LinkedServer cut my connection because it takes more than 10 minutes. The purpose of the query is to get newer data from a different database if it exists (i get newest data by top and ordering it by date and precondition is that every data in that database is newer than in mine, thats why im using COALESCE).
But my though is if I was able to rewrite it to JOIN it could be faster. But another problem could be I dont have an primary key (and cant change that).
How can I speed that query up ? (Im using SQL Server 2008 R2)
Thank you
Here i attached Estimated Query Plan: (Its readable in browser ZOOM :) Estimation is for 2 Coalesce columns.
Try rewriting query using outer apply
SELECT
t1.Column1
,t2.Column2
,COALESCE(ou.vat, m.Vat) as Vat
FROM Table1 t1
JOIN Table2 m on (m.Column1 = t1.Column1)
outer apply
(
SELECT TOP 1 Vat
FROM LinkedDBServer.DatabaseName.dbo.TableName t3
WHERE
m.MaterialNumber = t3.MaterialNumber COLLATE Czech_CI_AS
and t3.Currency = …
and ...
ORDER BY [Date] DESC
) ou
Another option:
; WITH vat AS (
SELECT MaterialNumber COLLATE Czech_CI_AS As MaterialNumber
, Vat
, Row_Number() OVER (PARTITION BY MaterialNumber ORDER BY "Date" DESC) As sequence
FROM LinkedDBServer.DatabaseName.dbo.TableName
WHERE Currency = ...
AND ...
)
SELECT t1.Column1
, m.Column2
, Coalesce(vat.Vat, m.Vat) As Vat
FROM Table1 As t1
INNER
JOIN Table2 As m
ON m.Column1 = t1.Column1
LEFT
JOIN vat
ON vat.MaterialNumber = m.MaterialNumber
AND vat.sequence = 1
;

Parsing simplified SQL queries with Perl into SQLite

I am trying to turn a "simplified" sql query into a working SQLite one to use against XnViews databases, meaning the database layout is at best suboptimal for what I'm trying to do AND I can't change anything about that.
Example would be "(cat_10 and cat_12) and (cat_5 or cat_7)".
This should be used against the table "t3", which has the fields "if" (fileID) and "ic" (categoryID).
The entries look like this:
if, ic
7, 10
7, 12
7, 4
9, 10
9, 12
9, 5
10, 10
10, 12
10, 7
The simplified query above should only select the files 9 and 10 as 7 does have the wanted categories 10 and 12 but has neither 5 nor 7.
The actual problem now is building that hell of a query statement because it took me already some hours to simply get an AND between two categories working.
SELECT if FROM t3 WHERE ic IN (10, 12) GROUP BY if HAVING count(if) = 2
This gives me all fileIDs that contain category 10 and 12, but I have no idea how I should combine that with the remaining " and (cat_5 or cat_7)".
When I planned these simplified sql statements (made by a click-it-together-builder made in html and js) I was planning to simply replace "cat_5" with "t3.ic = 5" and leave the rest as it is.
Of course I didn't forsee that it wouldn't work as where checks the entry as a whole and there can't be ic = 5 AND ic = 7. That pretty much broke everything.
So I'm wondering if anyone would have an idea how I could translate these simple queries in actual working ones, keeping in mind that it might not be limited to ( x and y ) pairs.
Edit: I worked out how to do the example I've given, I think atleast:
SELECT if FROM t3 WHERE ic IN (10, 12) GROUP BY if HAVING count(if) = 2
INTERSECT
SELECT if FROM t3 WHERE ic IN (5, 7) GROUP BY if
But the main problem now is resolving the ( ) in the right order.
Edit 2: I think I'm giving grouping the categories into one field with group_concat() a try, then I should be able to simply to cats LIKE " " AND which would be small blocks I could easy throw together, then just the brackets and it should work. Highlighting the 'should'.
Your original query doesn't do what is intended. WHERE ic IN (10, 12) GROUP BY if HAVING count(if) = 2 would yield the right result even when you have ics in 10 and 10 again but not 12 at all. This is against your textual description of what you want. This is where an inner query to fetch results for 12 and 10 is needed. You can test your query to fail in the fiddle link I have posted below.
Bit tricky, but this is how I would interpret it straightforward.
SELECT DISTINCT ifc
FROM t3
WHERE ifc IN (
SELECT ifc
FROM t3
WHERE ic = 10
GROUP BY ifc
HAVING COUNT(*) > 0
INTERSECT
SELECT ifc
FROM t3
WHERE ic = 12
GROUP BY ifc
HAVING COUNT(*) > 0
)
AND ic IN (5, 7)
Try fiddle
I did not bring in any optimization, you may try yours. The fiddle link is of Postgres but this should work ( did not get SQLite to work in my browser :( )
Edit: CL. points out an interesting thing about not having to include HAVING clauses in the inner query which is true. I was interpreting OP's requirement in SQL terms with an intent to make things clear without thinking of any optimizations.
Here is a better looking query:
SELECT DISTINCT ifc
FROM t3
WHERE ifc IN (
SELECT ifc
FROM t3
WHERE ic = 10
INTERSECT
SELECT ifc
FROM t3
WHERE ic = 12
)
AND ic IN (5, 7)
Ok I got it working as I originally planned surprisingly.
SELECT Folders.Pathname || Images.Filename AS File FROM Images
JOIN Folders ON Images.FolderID = Folders.FolderID
LEFT JOIN (
SELECT f, Cats, t4.if AS Tagged FROM t2
JOIN (
SELECT if, ' ' || group_concat(ic,' ') || ' ' AS Cats FROM t3 GROUP BY if
) st3 ON t2.i = st3.if
LEFT JOIN t4 ON t2.i = t4.if
) st2 ON File = st2.f
$selectWhereImage $sqlqry
ORDER BY ModifiedDate $order LIMIT $offset, $limit
I know this is one hell of a query but it combines all things I'd be looking for (category ids, tagged or not, rating, color) sortable by date with the full filepath as result.
It's probably a horrible way to do it but if anyone finds a better working way where I can simply replace placeholders like "cat_5" while keeping the rest like it is, needed for brackets and operators, then I'm all ears :D
Oh and $selectWhereImage contains just a longer WHERE that limits File to be ending with an imageformat, $sqlqry is the refittet thing from above, cat_5 would just turn into cats LIKE '% 5 %', due to the additional spaces left and right of cats I can match any number without finding "1" in "10" since " 1 " isn't in " 10 " :D
A hackish approach which would be simpler and I believe faster is
SELECT DISTINCT ifc
FROM t3
WHERE ifc IN (
SELECT ifc
FROM t3
WHERE ic = 10
)
AND ifc IN (
SELECT ifc
FROM t3
WHERE ic = 12
)
AND ic IN (5, 7)
If you have to use an intersect as you have done you should change your upper query which is wrong. Since you have to ensure every if has a 10 and 12 as ic then you can't get away without two separate queries for that. Something like:
SELECT ifc
FROM t3
WHERE ifc IN (
SELECT ifc
FROM t3
WHERE ic = 10
)
AND ifc IN (
SELECT ifc
FROM t3
WHERE ic = 12
)
INTERSECT
SELECT ifc FROM t3 WHERE ic IN (5, 7)
The INTERSECT will handle the group by here so you dont have to explicitly add but this will not be as efficient as my other queries. If you have to get away with subqueries, you can use JOIN:
SELECT DISTINCT t.ifc
FROM t3 AS t
JOIN t3 AS v ON v.ifc = t.ifc
JOIN t3 AS p ON p.ifc = t.ifc
WHERE v.ic = 10 AND p.ic = 12 AND t.ic IN (5, 7)
The second one has the advantage that it works on databases that doesn't know INTERSECT like MySQL.