Sum by group in foxpro - sum

I'm newbie in foxpro programming. i have some issue how to fill "sum value" column with value data from second column by id_doc from first column. Thankyou
From this
table 1
Table1
Id_doc Value Sum_Value
AA 12 ??
AA 11 ??
AA 14 ??
BB 9 ??
BB 8 ??
CC 7 ??
CC 10 ??
CC 13 ??
To This Table
Table results
I have try this
SELECT id_doc, SUM(NILAI) as Jml;
FROM table2;
GROUP BY Id_doc;
INNER JOIN Jml_nilai as Jml ;
ON Id_doc = Id_doc;
ORDER BY Id_doc ASCENDING;
But it's not running well....

Your current description looks as if you want this:
CREATE CURSOR table1 (id_doc Char(20), value Int, sum_value Int)
INSERT INTO table1 (id_doc, value) VALUES ('AA', 12)
INSERT INTO table1 (id_doc, value) VALUES ('AA', 11)
INSERT INTO table1 (id_doc, value) VALUES ('AA', 14)
INSERT INTO table1 (id_doc, value) VALUES ('BB', 9)
INSERT INTO table1 (id_doc, value) VALUES ('BB', 8)
INSERT INTO table1 (id_doc, value) VALUES ('BB', 7)
INSERT INTO table1 (id_doc, value) VALUES ('CC', 7)
INSERT INTO table1 (id_doc, value) VALUES ('CC', 10)
INSERT INTO table1 (id_doc, value) VALUES ('CC', 13)
SELECT id_doc, SUM(value) FROM table1 GROUP BY id_doc
Edited: This could be the "running group sums self-Join" SQL as mentioned in the currently last comment:
SELECT T1.id_doc, T1.value, T2.grpSum FROM table1 T1 ;
JOIN (SELECT id_doc, SUM(value) as grpSum FROM table1 GROUP BY id_doc) T2 ;
On T2.id_doc = T1.id_doc
Later: learned that it's rather called [groupwise-maximum]
https://stackoverflow.com/questions/tagged/groupwise-maximum

Thank you so much for all response. Finally it's done....
Sharing for all. This is what i did.
CLOSE all
SET SAFETY OFF
******************************************************************
USE table1.dbf
INDEX on id_doc TO a
TOTAL ON id_doc TO table1_jumlah.dbf
CLOSE ALL
*************************************************************
sele 1
* data primer (master)
use table1_jumlah.dbf
index on id_doc to i
sele 2
* data sekunder (diisi)
use table1.dbf
index on id_doc to ii
sele 1
go top
do while .not. eof()
iddocx=Id_doc
valuex=Value
sele 2
loca for id_doc=iddocx
if found()
repl ALL Sum_Value with Valuex for id_doc=iddocx
endi
sele 1
skip
loop
endd
**********************************************************
CLOSE ALL
DELETE FILE *.bak
DELETE FILE *.idx

Related

SQL , self join

I have a set of data
name
AASADF2
AASADF3
ADSFFD2
ADSFFD3
AAWFWEF
SFASFSF
ADAQWEW
ASDAWFA
FSDGFRG
AFWEFR2
AFWEFR3
I wanted to retrieve data with name ending 2 or 3 also first 6 character should match
i.e
AASADF2
AASADF3
ADSFFD2
ADSFFD3
AFWEFR2
AFWEFR3
I was able to display the data vertically using self join
AASADF2 AASADF3
ADSFFD2 ADSFFD3
AFWEFR2 AFWEFR3
But I wanted that in horizontal format
AASADF2
AASADF3
ADSFFD2
ADSFFD3
AFWEFR2
AFWEFR3
Do we need to create temp table for this to acheive this format
Any thoughts?
Is this what you want :
select t.*
from table t
where right(nm, 1) in ('2', '3') and
exists (select 1 from table t1 where left(t1.nm, 6) = left(t.nm, 6))
One method uses window functions:
select t.*
from (select t.*, count(*) over (partition by left(t.field, 6)) as cnt
from t
) t
where cnt > 1 and field like '%[23]';
SELECT distinct t1.field FROM TABLE t1 JOIN TABLE t2
ON t1.field != t2.field
AND RIGHT(t1.field,1 ) IN ('2', '3')
AND LEFT(t1.field, 6) = LEFT(t2.field,6);
--*********************************************
here is a full example for you
DECLARE #table TABLE
(
field nvarchar(10)
)
insert #table (field) values ('AASADF2'),
('AASADF3'),
('ADSFFD2'),
('ADSFFD3'),
('AAWFWEF'),
('SFASFSF'),
('ADAQWEW'),
('ASDAWFA'),
('FSDGFRG'),
('AFWEFR2'),
('AFWEFR3');
SELECT distinct t1.field FROM #table t1 JOIN #table t2
ON t1.field != t2.field
AND RIGHT(t1.field,1 ) IN ('2', '3')
AND LEFT(t1.field, 6) = LEFT(t2.field,6)
output
field
----------
AASADF2
AASADF3
ADSFFD2
ADSFFD3
AFWEFR2
AFWEFR3
(6 row(s) affected)
I was able to retrieve partial results,
If we check count > 1 which will show the results which I am looking for , I used the below query
;with cte as
(select t1.name from t_name t1
where substring(t1.name, 8, 1) in
(
select substring(t2.name, 8, 1) from t_name t2
where
substring(t2.name, 8, 1)='2'
or substring(t2.name, 8, 1)='3'
)
)
B2018BT2 1
B2018BU2 1
B2018BV2 1
B2018BW2 1
B2018BX2 1
B2018BY2 1
B2018BZ2 1
B2020AA2 2
B2020AA3 2
B2020AB2 2
B2020AB3 2
B2020AC2 2
B2020AC3 2
Can someone suggest how to do a filer on count>1?

sql generate code based on three column values

I have three columns
suppose
row no column1 column2 column3
1 A B C
2 A B C
3 D E F
4 G H I
5 G H C
I want to generate code by combining these three column values
For Eg.
1)ABC001
2)ABC002
3)DEF001
4)GHI001
5)GHC001
by checking combination of three columns
logic is that
if values of three columns are same then like first time it shows 'ABC001'
and 2nd time it shows 'ABC002'
You can try this:
I dont know what you want for logic with 00, but you can add them manuel or let the rn decide for you
declare #mytable table (rowno int,col1 nvarchar(50),col2 nvarchar(50),col3 nvarchar(50)
)
insert into #mytable
values
(1,'A', 'B', 'C'),
(2,'A', 'B', 'C'),
(3,'D', 'E', 'F'),
(4,'G', 'H', 'I'),
(5,'G', 'H', 'C')
Select rowno,col1,col2,col3,
case when rn >= 10 and rn < 100 then concatcol+'0'+cast(rn as nvarchar(50))
when rn >= 100 then concatcol+cast(rn as nvarchar(50))
else concatcol+'00'+cast(rn as nvarchar(50)) end as ConcatCol from (
select rowno,col1,col2,col3
,Col1+col2+col3 as ConcatCol,ROW_NUMBER() over(partition by col1,col2,col3 order by rowno) as rn from #mytable
) x
order by rowno
My case when makes sure when you hit number 10 it writes ABC010 and when it hits above 100 it writes ABC100 else if its under 10 it writes ABC001 and so on.
Result
TSQL: CONCAT(column1,column2,column3,RIGHT(REPLICATE("0", 3) + LEFT(row_no, 3), 3))
You should combine your columns like below :
SELECT CONVERT(VARCHAR(MAX), ROW_NUMBER() OVER(ORDER BY
(
SELECT NULL
)))+') '+DATA AS Data
FROM
(
SELECT column1+column2+column3+'00'+CONVERT(VARCHAR(MAX), ROW_NUMBER() OVER(PARTITION BY column1,
column2,
column3 ORDER BY
(
SELECT NULL
))) DATA
FROM <table_name>
) T;
Result :
1)ABC001
2)ABC002
3)DEF001
4)GHI001
5)GHC001
MySQL:
CONCAT(column1,column2,column3,LPAD(row_no, 3, '0'))
[you will need to enclose the 'row no' in ticks if there is a space in the name of the field instead of underscore.]

SQL Server 2012, update record based on next record

I'm struggling to find a solution to update (not just select) SQL table records based on previous values. I can get the script to populate the immediate subsequent record with the LAG() function, but when I have the same values in a row (like 'CC' below) I can't get it to populate with the next value that's not the same as the current value.
It would also be helpful to be able to add CASE/WHEN condition so that only values with the same BaseID are evaluated. Any help would be greatly appreciated.
Here is my desired result:
BaseID Value Date NextValue
1 AA 2017-10-01 BB
1 BB 2017-10-02 CC
1 CC 2017-10-03 DD
1 CC 2017-10-03 DD
1 CC 2017-10-03 DD
1 DD 2017-10-04 NULL
2 EE 2017-10-01 FF
2 FF 2017-10-02 GG
2 GG 2017-10-03 NULL
Get the distinct baseid,value,date combinations and use lead to get the next value in a cte and use itto update.
with cte as (select t1.baseid,t1.value,t1.nextvalue,t2.nxt_value
from tbl t1
left join (select t.*,lead(value) over(partition by baseid order by datecol) as nxt_value
from (select distinct baseid,datecol,value from tbl) t
) t2
on t1.baseid=t2.baseid and t1.datecol=t2.datecol and t1.value=t2.value
)
update cte set nextvalue=nxt_value
This assumes there can't be multiple values for a given baseid,date combination.
Here is a working example using DENSE_RANK as another option.
declare #Something table
(
BaseID int
, MyValue char(2)
, MyDate date
, NextValue char(2)
)
insert #Something
(
BaseID
, MyValue
, MyDate
) VALUES
(1, 'AA', '2017-10-01')
, (1, 'BB', '2017-10-02')
, (1, 'CC', '2017-10-03')
, (1, 'CC', '2017-10-03')
, (1, 'CC', '2017-10-03')
, (1, 'DD', '2017-10-04')
, (2, 'EE', '2017-10-01')
, (2, 'FF', '2017-10-02')
, (2, 'GG', '2017-10-03')
;
with SortedResults as
(
select *
, DENSE_RANK() over(partition by BaseID order by BaseID, MyDate ) as MyRank
from #Something
)
update sr set NextValue = sr2.MyValue
from SortedResults sr
join SortedResults sr2 on sr2.MyRank - 1 = sr.MyRank and sr.BaseID = sr2.BaseID
select *
from #Something

i want to display data according to type in same query

i have following table "vehicle_data" :
ID ALERT_TYPE VALUE
58 2 1
58 1 1
104 1 1
104 2 1
Here alert_type = 2 is for GPS value and alert_type=1 is for engine_value .
so if alert_type=2 and its value is =1 then it means its value is correct.
when alert_type=2 and its value is =0 then it means its value is wrong.
same for alert_type=1
so now here i want the following output:
ID gps engine_value
58 1 1
104 1 1
how can i perform this query??
You can do it like this.
SELECT ID
,CASE WHEN [ALERT_TYPE]=2 and [value ]=1 THEN 1 ELSE 0 END as gps
,CASE WHEN [ALERT_TYPE]=1 and [value ]=1 THEN 1 ELSE 0 END as engine
FROM vehicle_data
SELECT ID, alert_type=2 AS gps, alert_type=1 AS [engine] FROM vehicle_data WHERE value=1;
EDITED to account for your explanation of VALUE.
Schema
CREATE TABLE table3 (id int, ALERT_TYPE int)
INSERT table3 VALUES (58, 1), (58, 2), (104, 1), (104, 2)
Query
SELECT *
FROM (
SELECT ID
,ROW_NUMBER() OVER (
PARTITION BY id ORDER BY id
) AS row_num
,gps = CASE
WHEN ALERT_TYPE = 2
THEN 1
ELSE 0
END
,engine = CASE
WHEN ALERT_TYPE = 1
THEN 1
ELSE 0
END
FROM table3
) a
WHERE a.row_num = 1
Output
ID gps engine
58 1 0
104 0 1
One possible way using subqueries :
select
Ids.ID
, gps.VALUE 'gps'
, engine_value.VALUE 'engine_value'
from (select distinct ID from vehicle_data) Ids
left join
(select ID, VALUE from vehicle_data where ALERT_TYPE = 2) gps
on gps.ID = Ids.ID
left join
(select ID, VALUE from vehicle_data where ALERT_TYPE = 1) engine_value
on engine_value.ID = Ids.ID
[SQL Fiddle demo]
I hope this should work for you,
Select ID,sum(gps) as gps ,sum(engine) as engine from
(SELECT ID
,CASE WHEN [ALERT_TYPE]=2 and [value ]=1 THEN 1 ELSE 0 END as gps
,CASE WHEN [ALERT_TYPE]=1 and [value ]=1 THEN 1 ELSE 0 END as engine
FROM vehicle_data
)a
group by id
select x.id,x.alert_type as GPS,x.value as engine_value from (
select ID,alert_type,value,ROW_NUMBER() over (partition by id order by alert_type ) as Rnk from mytable
)x
where Rnk=1
Please check this query in SQL :
create table mytable (id int, alert_type int, value int);
insert into mytable (id, alert_type, value)
values (58, 2, 1),
(58, 1, 1),
(104, 1, 1),
(104, 2, 1);
SELECT distinct ID
,(select count (id) from mytable mt where mt.id=mytable.id and mt.[ALERT_TYPE]=2 and mt.[value ]=1) as gps
,(select count (id) from mytable mt where mt.id=mytable.id and mt.[ALERT_TYPE]=1 and mt.[value ]=1) as engine
FROM mytable
BASED ON YOUR QUESTION I BELIEVE YOU WANT THE DATA IN COLUMN AND TO SUIT YOUR REQUIREMENT I HAVE MADE A SQL FIDDLE WORKING - CODE IS ALSO MENTIONED BELOW -
HERE YOU GO WITH THE WORKING FIDDLE -
WORKING DEMO
SQL CODE FOR REFERNECE -
CREATE TABLE ALERTS (ID INT, ALERT_TYPE INT, VALUE INT)
INSERT INTO ALERTS VALUES (58,2,1)
INSERT INTO ALERTS VALUES (58,1,0)
INSERT INTO ALERTS VALUES (104,1,1)
INSERT INTO ALERTS VALUES (104,2,0)
CREATE TABLE ALERTSVALUE (ID INT, gps INT,engine INT)
INSERT INTO ALERTSVALUE VALUES (58,1,0)
INSERT INTO ALERTSVALUE VALUES (104,0,1)
SELECT A.ID,
CASE A.ALERT_TYPE WHEN 2 THEN 1 ELSE 0 END AS GPS,
CASE A.ALERT_TYPE WHEN 1 THEN 1 ELSE 0 END AS ENGINE_VALUE,
A.VALUE FROM ALERTS A WHERE A.VALUE = 1
EDIT BASED ON COMMENT - TO MERGE THE ROWS FOR BOTH GPS AND ENGINE_VALUE:
SELECT X.ID,X.ALERT_TYPE as GPS,X.VALUE as ENGINE_VALUE
FROM (
SELECT ID,ALERT_TYPE ,VALUE ,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY alert_type ) AS [Rank] FROM ALERTS
)X
WHERE [Rank]=1
SQL FIDDLE DEMO

How can I find duplicate consecutive values in this table?

Say I have a table which I query like so:
select date, value from mytable order by date
and this gives me results:
date value
02/26/2009 14:03:39 1
02/26/2009 14:10:52 2 (a)
02/26/2009 14:27:49 2 (b)
02/26/2009 14:34:33 3
02/26/2009 14:48:29 2 (c)
02/26/2009 14:55:17 3
02/26/2009 14:59:28 4
I'm interested in the rows of this result set where the value is the same as the one in the previous or next row, like row b which has value=2 the same as row (a). I don't care about rows like row (c) which has value=2 but does not come directly after a row with value=2. How can I query the table to give me all rows like (a) and (b) only? This is on Oracle, if it matters.
Use the lead and lag analytic functions.
create table t3 (d number, v number);
insert into t3(d, v) values(1, 1);
insert into t3(d, v) values(2, 2);
insert into t3(d, v) values(3, 2);
insert into t3(d, v) values(4, 3);
insert into t3(d, v) values(5, 2);
insert into t3(d, v) values(6, 3);
insert into t3(d, v) values(7, 4);
select d, v, case when v in (prev, next) then '*' end match, prev, next from (
select
d,
v,
lag(v, 1) over (order by d) prev,
lead(v, 1) over (order by d) next
from
t3
)
order by
d
;
Matching neighbours are marked with * in the match column,
This is a simplified version of #Bob Jarvis' answer, the main difference being the use of just one subquery instead of four,
with f as (select row_number() over(order by d) rn, d, v from t3)
select
a.d, a.v,
case when a.v in (prev.v, next.v) then '*' end match
from
f a
left join
f prev
on a.rn = prev.rn + 1
left join
f next
on a.rn = next.rn - 1
order by a.d
;
As #Janek Bogucki has pointed out LEAD and LAG are probably the easiest way to accomplish this - but just for fun let's try to do it by using only basic join operations:
SELECT mydate, VALUE FROM
(SELECT a.mydate, a.value,
CASE WHEN a.value = b.value THEN '*' ELSE NULL END AS flag1,
CASE WHEN a.value = c.value THEN '*' ELSE NULL END AS flag2
FROM
(SELECT ROWNUM AS outer_rownum, mydate, VALUE
FROM mytable
ORDER BY mydate) a
LEFT OUTER JOIN
(select ROWNUM-1 AS inner_rownum, mydate, VALUE
from mytable
order by myDATE) b
ON b.inner_rownum = a.outer_rownum
LEFT OUTER JOIN
(select ROWNUM+1 AS inner_rownum, mydate, VALUE
from mytable
order by myDATE) c
ON c.inner_rownum = a.outer_rownum
ORDER BY a.mydate)
WHERE flag1 = '*' OR
flag2 = '*';
Share and enjoy.