I have a file like this:
COUNTRY | 2008 | 2009 | 2010 | 2011 | 2012 | TYPE
SPAIN 5 41 8 12 5 T1
SPAIN 4 6 2 7 14 T2
SPAIN 7 8 9 6 2 T3
FRANCE 4 5 7 9 66 T1
FRANCE 14 3 4 12 12 T2
FRANCE 5 8 11 3 6 T3
...
And I need to convert it into a format like:
COUNTRY | YEAR | T1 | T2 | T3
SPAIN 2008 5 4 7
SPAIN 2009 41 6 8
....
Thanks
If you're talking about Pentaho Data Integration you can use the Row Normalizer step. It allows you to define the columns that hold measure types, and convert them into a single "type" column.
Check the documentation for examples of usage.
Related
I'm working with an Access database and have two tables:
ID_1
Number
Some other data
1
1
Data
2
2
Data
3
3
Data
4
4
Data
5
3
Data
6
1
Data
7
2
Data
8
3
Data
9
1
Data
10
1
Data
11
2
Data
12
3
Data
13
4
Data
14
1
Data
15
2
Data
16
3
Data
17
4
Data
18
3
Data
19
3
Data
ID_2
Number
Some other data
1
3
Data
2
1
Data
3
2
Data
4
3
Data
5
2
Data
As you see, both tables have duplicate data. I need a query that would select all the records in the first table that match each of the records in the second, they are related by Number field. It's also necessary that these records aren't repeated (that is, that the query doesn't repeat values when selecting). For the given example I should get this result:
ID
ID_1
Number
Some other data
1
3
3
Data
2
5
3
Data
3
8
3
Data
4
12
3
Data
5
16
3
Data
6
18
3
Data
7
19
3
Data
8
1
1
Data
9
6
1
Data
10
9
1
Data
11
10
1
Data
12
14
1
Data
13
2
2
Data
14
7
2
Data
15
11
2
Data
16
15
2
Data
I was thinking that maybe I could use Join, but I still don't know how; tried Where, but also didn't find a use for it. Could you please help me with that?
I don't see where you're generating your output ID field from - or where you're picking your Data field from so here's the best guess.
SELECT Table1.ID_1, Table1.Number, Table1.[Some other data]
FROM Table1
WHERE (Table1.Number In (SELECT Number From Table2))
ORDER BY Table1.Number, Table1.ID_1;
Looks like this:
MySql DB data structure
create table tbl1(ID_1 serial, Number int);
create table tbl2(ID_2 serial, Number int);
insert into tbl1(Number) values (1),(2),(3),(4),(3),(1),(2),(3),(1),(1),(2),(3),(4),(1),(2),(3),(4),(3),(3);
insert into tbl2(Number) values (3),(1),(2),(3),(2);
query (with s), needed to remove duplicates
the window function count(tbl1.Number) OVER(PARTITION BY Number) sorts the result for us by the count of matched numbers
the #rownum variable is needed to count rows
with s as (select distinct Number from tbl2),
f as (select ID_1,tbl1.Number from tbl1 left join s on
(tbl1.Number=s.Number) where s.Number is not null order by
count(tbl1.Number) OVER(PARTITION BY Number) desc)
select #rownum := #rownum + 1 AS ID,ID_1,Number from f, (SELECT #rownum := 0) r;
results
+------+------+--------+
| ID | ID_1 | Number |
+------+------+--------+
| 1 | 3 | 3 |
| 2 | 5 | 3 |
| 3 | 8 | 3 |
| 4 | 12 | 3 |
| 5 | 16 | 3 |
| 6 | 18 | 3 |
| 7 | 19 | 3 |
| 8 | 1 | 1 |
| 9 | 6 | 1 |
| 10 | 9 | 1 |
| 11 | 10 | 1 |
| 12 | 14 | 1 |
| 13 | 2 | 2 |
| 14 | 7 | 2 |
| 15 | 11 | 2 |
| 16 | 15 | 2 |
+------+------+--------+
How do I select a pair (number, number) where tabid is equal for two numbers from the following table (i.e: number 7 and 11 have the same tabid):
tabid | number
---------+--------
1 | 6
1 | 6
2 | 7
3 | 8
4 | 8
5 | 10
5 | 11
6 | 12
6 | 11
5 | 6
4 | 7
3 | 8
2 | 11
The result of this should be:
number | number
---------+--------
7 | 11
7 | 8
10 | 11
11 | 12
6 | 10
6 | 11
Is this what you're looking for:
select
t1.number, t2.number
from t t1, t t2
where t1.tabid = t2.tabid
and t1.number < t2.number;
produces:
NUMBER NUMBER
---------- ----------
6 10
6 11
7 8
7 11
10 11
11 12
Use array_agg to concatenate the tabid's into an array. Thereafter self join this cte to check if one array is an overlap of the other using the array operator &&.
with concatenated as (
select array_agg(tabid) as arr_tab, num
from t
group by num
)
select c1.num,c2.num
from concatenated c1
join concatenated c2 on c1.num < c2.num
where c2.arr_tab && c1.arr_tab
order by 1,2
Sample Demo
I already made a query that this was it result :
7 | 3
8 | 4
8 | 2
8 | 1
10 | 3
12 | 4
12 | 1
13 | 3
I need new query that take this result and return this :
7 | 3
8 | **7**
10 | 3
12 | **5**
13 | 3
In the left column I need that evry number will appears only once,
and in the right column sum the numbers according to the value in the left column as I showed before.
how to do it?
SELECT leftField, SUM(rigthField) as rigthField
FROM YourResult
GROUP BY leftField
Let's suppose I have 3 tables right now, One table with lessons, one table with the ratings of those lessons, and one table with the users of those lessons.
Lessons is a quite regular table, and the other 2 tables are relation tables like this:
TABLE LESSONS
ID | NAME | DESCRIPTION | CREATED BY | APPROVED BY | LEVEL | DATE CREATED | LAST EDIT
1 les1 desc1 10 12 1 12-12-2000 12-12-2000
2 les2 desc2 23 12 2 12-12-2000 12-12-2000
3 les3 desc3 12 12 3 12-12-2000 12-12-2000
TABLE RATINGS
ID | LESSON | USER | RATING | COMMENT
1 1 60 5 very good
2 2 30 4 nice
3 2 62 4 my comment
4 3 65 3 nice
5 3 78 5 very good
6 1 26 1 very bad
6 1 45 3 other comment
TABLE LESSONSXUSERS
ID | LESSON | USER | STATUS
1 1 60 2
2 1 26 2
2 1 45 2
3 2 30 2
4 2 62 2
5 3 65 2
6 3 78 2
7 1 22 1
8 1 19 1
And I'm trying to generate a view that shows me only approved lessons, with some info extracted from the other two tables:
CREATE OR REPLACE VIEW `skn_approved_lessons` AS
select
`l`.`id_skn_lessons` AS `id_skn_lessons`,
`l`.`name` AS `name`,
`l`.`description` AS `description`,
`l`.`createdBy` AS `createdBy`,
`l`.`approvedBy` AS `approvedBy`,
`l`.`id_skn_lessonsLevels` AS `id_skn_lessonsLevels`,
`l`.`dateCreated` AS `dateCreated`,
`l`.`lastEdit` AS `lastEdit`,
AVG(`lr`.`rating`) AS `avgScore`,
COUNT(`lxu`.`id_skn_users`) AS `students`
from ((`skn_lessons` AS `l`
left join `skn_lessonsRatings` AS `lr` on `l`.`id_skn_lessons` = `lr`.`id_skn_lessons`) left join `skn_lessonsXusers` AS `lxu` on `lxu`.`id_skn_lessons` = `l`.`id_skn_lessons`)
where ((`l`.`approvedBy` is not null) and
(`l`.`approvedBy` <> `l`.`createdBy`))
group by `l`.`id_skn_lessons`;
It's "kinda" working, since it shows me what I want, but the amount of users is wrong. I know why this happens, but I don't know how to fix it.
Issue is, I should get this:
VIEW APPROVED
ID | NAME | DESCRIPTION | CREATED BY | APPROVED BY | LEVEL | DATE CREATED | LAST EDIT | AVG RATING | STUDENTS
1 les1 desc1 10 12 1 12-12-2000 12-12-2000 3 4
2 les2 desc2 23 12 2 12-12-2000 12-12-2000 4 2
3 les3 desc3 12 12 3 12-12-2000 12-12-2000 4 2
But I'm getting this:
VIEW APPROVED
ID | NAME | DESCRIPTION | CREATED BY | APPROVED BY | LEVEL | DATE CREATED | LAST EDIT | AVG RATING | STUDENTS
1 les1 desc1 10 12 1 12-12-2000 12-12-2000 3 15
2 les2 desc2 23 12 2 12-12-2000 12-12-2000 4 4
3 les3 desc3 12 12 3 12-12-2000 12-12-2000 4 4
Notice users column is wrong, what I'm really getting is the product of usersxamountOfRatings. It's making the query with each registry of user by each registry of rating, so I'll always get the usersxratings as the amount of users, which is NOT what I want.
I don't quite understand how to do the second join after grouping by lesson.id, that I guess will solve the issue.
Thanks in advance.
I believe all you need to do is to add the DISTINCT argument to the COUNT aggregate function as follows:
COUNT(DISTINCT lxu.id_skn_users)
Adding the DISTINCT argument will return the number of unique nonnull values from that column.
I see Barmar already put that into the comments above.
I need to obtain the last two digits of an integer. Each element placed in the tables comes as a full year ie. YYYY and I only want the last two digits, so that all the fields show
YEAR
----
09
00
89
where the initialy field was
YEAR
----
2009
2000
1989
EDIT: I get a complaint saying,
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
when i try
select right(cast(year as char),2) from subjects;
Postgres has borrowed (or inherited) the modulus operator from C:
SET search_path='tmp';
CREATE TABLE lutser ( year integer);
INSERT INTO lutser (year)
SELECT generate_series(1991,2012)
;
SELECT year
, year / 100 as c2
, year % 100 AS y2
FROM lutser
;
Result:
CREATE TABLE
INSERT 0 22
year | c2 | y2
------+----+----
1991 | 19 | 91
1992 | 19 | 92
1993 | 19 | 93
1994 | 19 | 94
1995 | 19 | 95
1996 | 19 | 96
1997 | 19 | 97
1998 | 19 | 98
1999 | 19 | 99
2000 | 20 | 0
2001 | 20 | 1
2002 | 20 | 2
2003 | 20 | 3
2004 | 20 | 4
2005 | 20 | 5
2006 | 20 | 6
2007 | 20 | 7
2008 | 20 | 8
2009 | 20 | 9
2010 | 20 | 10
2011 | 20 | 11
2012 | 20 | 12
(22 rows)
select substring(CAST(2012 as CHAR(4)), 3, 2)
I don't know if there is a LEN function on Postgres, but if it does, try this:
select SUBSTRING(year,len(year)-1,len(year))
You can also use below SQL query:
select to_char as year from to_char(current_timestamp, 'YY')
here we use last two digit of year from current_timestamp