I have a scenario where I need to display only non zero columns
id C1 C2 C3 C4
1 0 1 0 2
2 0 1 0 5
3 0 9 0 3
i want the output as below
id C2 C4
1 1 2
2 1 5
3 9 3
An SQL query always results in before-known columns. So you cannot do what you want to do in pure SQL. (And not being able to do something with SQL only is often a sign of a poor database design. Sometimes however it's that SQL is about how to get data, not how to display it.)
What you can do is get the columns' sums in one query, then build a new query dynamically (manually or within an app with Java, PHP or whatever programming language is used) that only selects the non-zero columns.
Related
Overview
I am trying to run a query to join some data in 3 tables in BigQuery (should apply to most relation databases like PostgreSQL as well) using SQLAlchemy Core.
Input Data
Table 1 (t1)
c1
c2
x
0
0
0
0
1
1
1
0
2
Table 2 (t2)
c1
c2
y
0
0
3
1
1
4
1
2
5
Table 3 (t3)
c1
c2
z
0
0
6
1
1
7
2
2
8
Desired Query
The query I am trying to run is
SELECT
*
FROM
t1
FULL OUTER JOIN
t2
USING (c1, c2)
FULL OUTER JOIN
t3
USING (c1, c2)
which yields (- indicates null):
c1
c2
x
y
z
0
0
0
3
6
0
1
1
-
-
1
0
2
-
-
1
1
-
4
7
1
2
-
5
-
2
2
-
-
8
Problem
The problem I am running into is that it does not seem possible to perform joins with USING in SQLAlchemy Core. In particular, the join method only supports an onclause and not USING.
The two solutions I am attempting are:
Try to get USING to work with a TextClause. This is proving difficult as I need to consume the resulting table, referring to the columns by name.
Try to do the joins with the provided SQLAlchemy join method. I am unable to replicate this query using JOINs with ON without making subqueries.
Any help would be appreciated. Thanks!
See the last two row where option_order is 0 but type is different. I want to keep them on first position for each type. How can I re-ordered the value of option_order column?
Here, the condition is, the '000' choice must be kept on first for each type by setting its position_order.
current table status:
MULTIPLE_CHOICE Table
id choice type option_order
1 AA 1 1
2 BB 1 2
3 CC 1 3
4 AAA 2 4
5 BBB 2 5
6 CCC 2 6
7 DDD 2 7
8 000 1 0
9 000 2 0
Required updated table:
This is what I need:
updated MULTIPLE_CHOICE Table
id choice type option_order
8 000 1 1
1 AA 1 2
2 BB 1 3
3 CC 1 4
9 000 2 5
4 AAA 2 6
5 BBB 2 7
6 CCC 2 8
9 DDD 2 9
The actual table is too big, so I cannot do this by edit. Please help for this complex query. I have no clue to solve this.
[Note: I need this to solve for mysql version 5.7]
Recalculate the whole column. Use, for example, user-defined variable:
UPDATE MULTIPLE_CHOICE
SET option_order = (#counter := #counter + 1)
WHERE (SELECT #counter := 0) = 0
ORDER BY type, choice;
fiddle
can you explain this condition: WHERE (SELECT #counter := 0) = 0. – HiddenHopes
This is a condition only formally - as you can see it is always TRUE. The aim of this construction is in variable initialization.
In SELECT queries we can initialise user-defined variables in separate subquery cross-joined to another tables, like:
SELECT {columnset}
FROM {tableset}
CROSS JOIN ( SELECT #variable := starting_value ) AS initialize_variables
{the rest clauses}
But we cannot do the same in UPDATE. The calculations are critically dependent by rows processing order, i.e. ORDER BY clause with the ordering expression which provides rows uniqueness is compulsory. But the subquery which initializes the variables will convert single-table UPDATE to multiple-table which does not support ORDER BY clause at all!
The way out of this situation is to initialize the variable in WHERE clause. When server builds query execution plan it evaluates all constant expressions, including ones in WHERE clause. Moreover, in UPDATE server MUST evaluate WHERE expression before updating because it must firstly determine the rows which will be updated, and only then update them. So the expression in WHERE will be evaluated before rows updating, and hence the variable will be initialized before rows iteration with guarantee.
I have data in multiple rows, and I need to combine data in similar columns and separate with a semi colon, to end up with one row with grouped by ID.
I have
ID Type
1 A
1 B
1 C
2 D
3 A
3 F
I want results to be
1 A;B;C
2 D
3 A;F
I have limited knowledge of access, but know this should be basic and easy. I appreciate assistance.
I have a column in table A. the column name is Sequence number. The Structure of table A is numbers from 1,2,3,4.....3600.
Now on the basis of table A. I want the below output from the SQL select query for SQL server 2008.
seq no dynamic col
1 1
2 1
3 1
4 1
5 1
6 2
7 2
8 2
9 2
10 2
11 2
12 3
13 3
My Second column is getting generated at the run time.
And the business logic is that, if the seq number mod 6 = 0 then increment the value of dynamic column.
Thanks in advance
Try this:
select seqno, (seqno/6) +1 dynamiccol
from t
Fiddle Demo
Take this as pseudo code because I'm not familiar with SQL Server specifically, but it should give you somewhere to go.
SELECT
seq_no,
ROUNDDOWN(seq_no/6)+1 AS dynamic_col
FROM
my_table
I'm way out of my league here...
I have a mapping table (table1) to assign particular values (value) to a whole number (map_nu). My second table (table2), is a collection of averages (avg) for each user (user_id).
(I couldn't figure out how to properly make a markdown table, please feel free to edit!)
table1: table2:
(value)(Map_nu) (user_id)(avg)
---- -----
1 1 1 1.111
1.045 2 2 1.2
1.09 3 3 1.33333
1.135 4 4 1
1.18 5 5 1.389
1.225 6 6 1.42
1.27 7 7 1.07
1.315 8
1.36 9
1.405 10
The value Map_nu is a special number that each user gets assigned according to their average. I need to find a way to match the averages from table2 to the closest value in table1. I only need to match to the 2 digit past the decimal, so I've added the Truncated function
SELECT table2.user_id, map_nu
FROM `table1`
JOIN table2 ON TRUNCATE(table1.value,2)=TRUNCATE(table2.avg,2)
I still miss the values that don't match the averages exactly. Is there a way to pick the nearest truncated value or even to round to the second decimal? Rounding up/down wont matter as long as its applied to all values the same.
I am trying to have the following result (if rounded up):
(user_id)(Map_nu)
----
1 4
2 6
3 6
4 1
5 10
6 11
7 3
Thanks!
i think you might have to do this in 2 separate queries. there is no 'nearest' operator in sql, so you can either calculate it in your software, or you could use
select map_nu from table1 ORDER BY abs(value - $avg) LIMIT 1
inside a loop. however, that cannot be used as a join function as it requires the ORDER and LIMIT which are not valid as joins.
another way of looking at it is it seems that your map_nu and value are deterministic in relation to each other - value = 1 + ((map_nu - 1) * 0.045) - so maybe you could make use of that fact and calculate an integer based on that equation? assuming that relationship holds true for all values of map_nu.
This is an awkward database design. What is the data representing and what are you trying to solve? There might be a better way.
Maybe do something like...
SELECT a.user_id, b.map_nu, abs(a.avg - b.value)
FROM
table2 a
join table1 b
left join table1 c on abs(a.avg - b.value) > abs(a.avg - c.value)
where c.value is null
order by a.user_id
Doesn't actually produce the same output as the one you were expecting for (doesn't do any rounding). Though you should be able to tweak it from there. Above query will produce the output below (w/ data you've provided):
user_id map_nu abs(a.avg - b.value)
------- ------ --------------------
1 3 0.0209999999999999
2 5 0.02
3 8 0.01833
4 1 0
5 10 0.016
6 10 0.0149999999999999
7 3 0.02
Beware though if you're dealing with large tables. Evaluate the explain of the above query if it'll be practical to run it within MySQL or if better to be done outside it.
Note 2: Will produce duplicate rows if there are avg values that are equi-distant to value values within table1 (Ex. if value for map_nu's 11 and 12 are 2 and 3 and someone get's an avg of 2.5). Your question doesn't really specify what to do for that so you might want to take that into account.
Its taking a little extra work, but I figure the easiest way to get my results will be to map all values to the second decimal place in table1:
1 1
1.01 1
1.02 1
1.03 1
1.04 1
1.05 2
1.06 2
1.07 2
1.08 2
1.09 3
1.1 3
1.11 3
1.12 3
1.13 3
1.14 4
...
Thanks for the suggestions! Sorry I couldn't present the question more clear.