I want join two temp tables with Full outer join but doesn't work properly
and allways just show #RMS values without #RMB !!
where and what's wrong in this code?
( #RMS without null )
create table #RMS
(
[Year] int,
[Month] int,
sTAccount bigint,
sRemaining bigint
)
insert into #RMS(Year,Month,sTAccount,sRemaining)
select
YEAR(Date) [Year],
DATEPART(MONTH,Date) [Month],
sum(TAccount) sTAccount,
sum(Remaining) sRemaining
from
SaleInvoices
group by YEAR(Date),DATEPART(MONTH,Date)
order by YEAR(Date),DATEPART(MONTH,Date)
( #RMB without null but sometimes #RMB Month Column Value and #RMS Month Column value is Different )
create table #RMB
(
[Year] int,
[Month] int,
bTAccount bigint,
bRemaining bigint
)
insert into #RMB(Year,Month,bTAccount,bRemaining)
select
YEAR(Date) [Year],
DATEPART(MONTH,Date) [Month],
sum(TAccount) bTAccount,
sum(Remaining) bRemaining
from
BuyInvoices
group by YEAR(Date),DATEPART(MONTH,Date)
order by YEAR(Date),DATEPART(MONTH,Date)
select * from #RMS
Full Outer Join #RMB
on #RMS.Year=#RMB.Year and #RMS.Month=#RMB.Month
group by #RMS.Year, #RMS.Month
order by #RMS.Year, #RMS.Month
Thanks For Your Answers
You have the wrong SELECT list. Replace * with #RMS.*, #RMB.* or (better) an explicit list of the fields you want, prefixing their names with the name of the table they come from. This also allows not to repeat the fields you've joined on.
Related
I have 2 tables, in one table i am saving cost based on different date batch and in another table i am saving the order date. What i need is to get cost from the table where order date falls between them.
create table #TempDateBatch
(
Sku nvarchar(50),
FromDate datetime,
ToDate datetime,
Cost decimal(12,2)
)
Insert into #TempDateBatch(Sku,FromDate,ToDate,Cost) values('Abc','2020-05-01','2020-05-31',12.3);
Insert into #TempDateBatch(Sku,FromDate,ToDate,Cost) values('Abc','2020-06-01','2020-06-05',10.3);
Create table #TempMain
(
Sku nvarchar(50),
ProductName nvarchar(50),
OrderDate datetime
)
Insert into #TempMain(Sku,ProductName,OrderDate) values('Abc','Demo Prdouct','2020-05-10');
Insert into #TempMain(Sku,ProductName,OrderDate) values('Abc','Demo Prdouct','2020-06-03');
I need to get Sku and Order date from one table and i need to pick cost from another table on the date which that order falls.
Example Something like this -:
I think you just want a join:
select m.*, db.cost
from #TempMain m left join
#TempDateBatch db
on m.sku = db.sku and
m.orderdate between db.fromdate and db.todate
Imagining I have the following table:
We can see that Tuna was not served in Month 1.
I would like to make it appear also in Month 1.
How can I achieve this?
Thank you !
You can try to use two subqueries with DISTINCT and CROSS JOIN
SELECT *
FROM (SELECT DISTINCT Food FROM T) t1
CROSS JOIN (SELECT DISTINCT [Month] FROM T) t2
sqlfiddle
You can use cross apply to give each food every month. That seems to be what you want.
declare #table table (Food varchar(16), [Month] int)
insert into #table
values
('Pizza',1),
('Burgers',1),
('Salad',1),
('Tuna',2),
('Pizza',2),
('Burgers',2),
('Salad',2)
select distinct
f.Food
,m.Month
from #table f
cross apply (select distinct [Month] from #table) m
order by m.Month
To find out what months Tuna was not served in...
select distinct [MONTH]
from #table
where [Month] not in (select [Month] from #table where Food = 'Tuna')
If I understand the issue is that you have a table without the record of the month for some type of food.
For me the best way its to create a table "month_of_year" that will contains only the number from 1 to 12.
then:
select distinct Food
into #tmp
from your_table
select a.Food, month_of_year.month
from #tmp a cross join month_of_year
drop table #tmp
then if you want for example see the total of food for the year, go in left from the last table that I have written with the table of the sum, and you will have all the food/month with the total and in case a null on the total where the food was not be served
If you need more information ask =)
I would like to populate table variable with results from CADEPA table. The only problem is that those results must be ordered.
The error I am receiving is:
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified.
Query is:
DECLARE #DEPARTMENTS_TBL TABLE
(
DEPA_KEY INT
)
INSERT INTO #DEPARTMENTS_TBL(DEPA_KEY)
SELECT DEPA_KEY
FROM (
SELECT DISTINCT DEPA_KEY
FROM CADEPA
WHERE DEPA_STA = '1'
ORDER BY DEPA_NME
) P
Tables represent unordered sets. To do what you want, you need a key to represent the ordering:
DECLARE #DEPARTMENTS_TBL TABLE (
ID IDENTITY(1, 1) PRIMARY KEY
DEPA_KEY INT
);
INSERT INTO #DEPARTMENTS_TBL (DEPA_KEY)
SELECT DEPA_KEY
FROM CADEPA
WHERE DEPA_STA = '1'
GROUP BY DEPA_KEY
ORDER BY MAX(DEPA_NME);
I also think you should include DEPA_NME in the table, but the id column will keep the ordering.
Be sure you query with order by:
select d.*
from DEPARTMENTS_TBL d
order by id;
Move order by clause at the end after you table alias (P)
INSERT INTO #DEPARTMENTS_TBL(DEPA_KEY)
SELECT DISTINCT DEPA_KEY
FROM (
SELECT DEPA_KEY, DEPA_NME
FROM CADEPA
WHERE DEPA_STA = '1'
) P
ORDER BY DEPA_NME
I have 2 tables that collect records of event on points.
CREATE TABLE report_one
(
date timestamp,
point_id bigint,
income int
)
CREATE TABLE report_two
(
date timestamp,
point_id bigint,
spent int
)
I want to generate a sum report (and addiitonal reports). i want to use join because i need to support pagination, ordering ...
The problem is that the join key (point id for the report) is not 1:1 , so i got the same row more than one.
insert into report_one values('2013-1-1',1,1)
insert into report_two values('2013-1-1',1,1)
insert into report_two values('2013-1-2',1,1)
select * from report_one r1 left join report_two r2 on r1.point_id = r2.point_id
will have 2 rows of table report_one ,but for total i need only one.
I want to be able to create a view of some kind of join between the tables, where each row will be only once.
**I want output like this:
1 (pid) , 1,1,0,0 - this from report_one
1 (pid) ,0,0,1,1 -- this from report_two
1 (pid) ,0,0,1,1 -- this from report_two **
Union all can be great , but i dont have the same columns types in the two tables.
Ps . The real table has lots of column and pk is more than one column , i just make is simple for the question
Why not try the following.
CREATE TABLE report
(
report_id bigint,
date varchar(20),
point_id bigint,
amount int,
amount_type varchar(20)
);
THEN
insert into report values (1,'2013-01-01',1,1,'income');
insert into report values (2,'2013-01-01',1,1,'expense');
insert into report values (2,'2013-01-02',1,1,'expense');
Finally
SELECT report_id,amount_type,SUM(point_id) FROM report GROUP BY report_id,amount_type
The output will sum point_id per report/amount_type then it will be easier to draw stats per date range, etc and overhead by create table and joins will also be minimized.
The output: SQL Fiddle Demo
I think that this can work for me:
select date d1,point_id p1,0 income ,spent spent from report_one
union ALL
select date d2,point_id p2,income,0 spent from report_two
I dont have to have the zero . I added them for demo a case that they the columns are not from the same type
You could group tables by point_id first, choosing more appropriate aggregate functions for the fields needed and then join to each other:
select r1.point_id, r1.date, r1.income, r2.spent
from
(
select point_id, max(date) date, sum(income) income
from report_one
group by point_id
) r1
inner join
(
select point_id, max(date) date, sum(spent) spent
from report_two
group by point_id
) r2 on r1.point_id = r2.point_id
Also, UNION way:
select point_id, date, income sum, 1 is_income
from report_one
union all
select point_id, date, spent sum, 0 is_income
from report_two
I have been trying to find some info on how to select a non-aggregate column that is not contained in the Group By statement in SQL, but nothing I've found so far seems to answer my question. I have a table with three columns that I want from it. One is a create date, one is a ID that groups the records by a particular Claim ID, and the final is the PK. I want to find the record that has the max creation date in each group of claim IDs. I am selecting the MAX(creation date), and Claim ID (cpe.fmgcms_cpeclaimid), and grouping by the Claim ID. But I need the PK from these records (cpe.fmgcms_claimid), and if I try to add it to my select clause, I get an error. And I can't add it to my group by clause because then it will throw off my intended grouping. Does anyone know any workarounds for this? Here is a sample of my code:
Select MAX(cpe.createdon) As MaxDate, cpe.fmgcms_cpeclaimid
from Filteredfmgcms_claimpaymentestimate cpe
where cpe.createdon < 'reportstartdate'
group by cpe.fmgcms_cpeclaimid
This is the result I'd like to get:
Select MAX(cpe.createdon) As MaxDate, cpe.fmgcms_cpeclaimid, cpe.fmgcms_claimid
from Filteredfmgcms_claimpaymentestimate cpe
where cpe.createdon < 'reportstartdate'
group by cpe.fmgcms_cpeclaimid
The columns in the result set of a select query with group by clause must be:
an expression used as one of the group by criteria , or ...
an aggregate function , or ...
a literal value
So, you can't do what you want to do in a single, simple query. The first thing to do is state your problem statement in a clear way, something like:
I want to find the individual claim row bearing the most recent
creation date within each group in my claims table
Given
create table dbo.some_claims_table
(
claim_id int not null ,
group_id int not null ,
date_created datetime not null ,
constraint some_table_PK primary key ( claim_id ) ,
constraint some_table_AK01 unique ( group_id , claim_id ) ,
constraint some_Table_AK02 unique ( group_id , date_created ) ,
)
The first thing to do is identify the most recent creation date for each group:
select group_id ,
date_created = max( date_created )
from dbo.claims_table
group by group_id
That gives you the selection criteria you need (1 row per group, with 2 columns: group_id and the highwater created date) to fullfill the 1st part of the requirement (selecting the individual row from each group. That needs to be a virtual table in your final select query:
select *
from dbo.claims_table t
join ( select group_id ,
date_created = max( date_created )
from dbo.claims_table
group by group_id
) x on x.group_id = t.group_id
and x.date_created = t.date_created
If the table is not unique by date_created within group_id (AK02), you you can get duplicate rows for a given group.
You can do this with PARTITION and RANK:
select * from
(
select MyPK, fmgcms_cpeclaimid, createdon,
Rank() over (Partition BY fmgcms_cpeclaimid order by createdon DESC) as Rank
from Filteredfmgcms_claimpaymentestimate
where createdon < 'reportstartdate'
) tmp
where Rank = 1
The direct answer is that you can't. You must select either an aggregate or something that you are grouping by.
So, you need an alternative approach.
1). Take you current query and join the base data back on it
SELECT
cpe.*
FROM
Filteredfmgcms_claimpaymentestimate cpe
INNER JOIN
(yourQuery) AS lookup
ON lookup.MaxData = cpe.createdOn
AND lookup.fmgcms_cpeclaimid = cpe.fmgcms_cpeclaimid
2). Use a CTE to do it all in one go...
WITH
sequenced_data AS
(
SELECT
*,
ROW_NUMBER() OVER (PARITION BY fmgcms_cpeclaimid ORDER BY CreatedOn DESC) AS sequence_id
FROM
Filteredfmgcms_claimpaymentestimate
WHERE
createdon < 'reportstartdate'
)
SELECT
*
FROM
sequenced_data
WHERE
sequence_id = 1
NOTE: Using ROW_NUMBER() will ensure just one record per fmgcms_cpeclaimid. Even if multiple records are tied with the exact same createdon value. If you can have ties, and want all records with the same createdon value, use RANK() instead.
You can join the table on itself to get the PK:
Select cpe1.PK, cpe2.MaxDate, cpe1.fmgcms_cpeclaimid
from Filteredfmgcms_claimpaymentestimate cpe1
INNER JOIN
(
select MAX(createdon) As MaxDate, fmgcms_cpeclaimid
from Filteredfmgcms_claimpaymentestimate
group by fmgcms_cpeclaimid
) cpe2
on cpe1.fmgcms_cpeclaimid = cpe2.fmgcms_cpeclaimid
and cpe1.createdon = cpe2.MaxDate
where cpe1.createdon < 'reportstartdate'
Thing I like to do is to wrap addition columns in aggregate function, like max().
It works very good when you don't expect duplicate values.
Select MAX(cpe.createdon) As MaxDate, cpe.fmgcms_cpeclaimid, MAX(cpe.fmgcms_claimid) As fmgcms_claimid
from Filteredfmgcms_claimpaymentestimate cpe
where cpe.createdon < 'reportstartdate'
group by cpe.fmgcms_cpeclaimid
What you are asking, Sir, is as the answer of RedFilter.
This answer as well helps in understanding why group by is somehow a simpler version or partition over:
SQL Server: Difference between PARTITION BY and GROUP BY
since it changes the way the returned value is calculated and therefore you could (somehow) return columns group by can not return.
You can use as below,
Select X.a, X.b, Y.c from (
Select X.a as a, sum (b) as sum_b from name_table X
group by X.a)X
left join from name_table Y on Y.a = X.a
Example;
CREATE TABLE #products (
product_name VARCHAR(MAX),
code varchar(3),
list_price [numeric](8, 2) NOT NULL
);
INSERT INTO #products VALUES ('paku', 'ACE', 2000)
INSERT INTO #products VALUES ('paku', 'ACE', 2000)
INSERT INTO #products VALUES ('Dinding', 'ADE', 2000)
INSERT INTO #products VALUES ('Kaca', 'AKB', 2000)
INSERT INTO #products VALUES ('paku', 'ACE', 2000)
--SELECT * FROM #products
SELECT distinct x.code, x.SUM_PRICE, product_name FROM (SELECT code, SUM(list_price) as SUM_PRICE From #products
group by code)x
left join #products y on y.code=x.code
DROP TABLE #products