Need help here
Is there a way to fix size of a box in body without growing more than the body itself ?
Here's the body :
When table 1 have more record it will add the height of the box while the range between table 1 and table 2 is the same.
What i need:
When table 1 have more record it will not add height of the box and consume the range between tb1 and tb2 until it's completely no more space then it will go to next page.
Is there a way to reach this ?
Here's some quick help:
Add a Rectangle (Rec1) with the top at the top of Table1 (T1) and ends at Table 2 (T2).
Put T1 in it.
When T1 grows, it will consume space in rectangle and NOT push down T2 AS LONG AS you limit T1 records to fit in Rec1.
You'll need to add a ROW_NUMBER to the SQL data.
Figure out how many records can fit and filter the table for that many by ROW_NUM (ROW_NUM <= 20).
Copy T1 and make T3 with ROW_NUM > 20.
Related
My tablix groups on one of its columns and only needs to output a list of time stamps for each row. As the time stamps are only two columns, that leaves an awful lot of wasted space.
Here is a basic mock-up of the current layout...
... and this is the desired layout:
As shown, the report would ideally adjust dynamically to display half the rows of a group in the left "column" (including the extra row if uneven) and the remaining rows in the right "column". Is this possible with SSRS? If not as described, can you suggest something with a similar result?
You can do this with as long as your dataset can be updated to support it.
First I grabbed some sample datetime data I had and inserted it into a table variable called #t. You'll just need to swap out #t for your actual table name. This gave me the following
Then I take this data and workout the row and column the data should sit in. In this example I am using a parameter to define the number of columns I want. You could do this and pass it in from your report if it's helpful, or just change it to a staic value. I'll demo with the parameter being passed in though.
Here's the query (Note you'll need to comment out the #Columns declaration if you want to pass this in from your report but for now we are just testing in SSMS or similar.
-- REPLACE #t with your actual tablename below
DECLARE #Columns int = 2 -- <= comment this out when you copy into your dataset query
SELECT
*
, ColumnNum = ((SortOrder-1) % #Columns) + 1
, RowNum = ROW_NUMBER() OVER(PARTITION BY GroupID, SortOrder % #Columns ORDER BY SortOrder)
FROM(
SELECT
ROW_NUMBER() OVER(PARTITION BY GroupID ORDER BY dt) as SortOrder,
GroupID, dt
FROM #t) x
ORDER BY GroupID, SortOrder
This gives us the following output
Now all we have to do is use a matrix control in the report to display it correctly.
Create a new report
Add a datsource and dataset
Set your dataset query as above remember to comment out the DECLARE #Columns line if you want to parameterise it.
Add a matrix control
Drag RowNum to the 'Rows' placeholder, dt to the 'data' placeholder and finally select ColNum in the columns placeholder
The matrix should look like this (we're not finished yet...)
In the row groups panel, drag GroupID above the exiting row group (above rownum in my example) so it creates a parent group.
Finally, add a blank row inside the RowGroup group by right-clicking the rownum textbox and doing "Insert Row, Inside Group - Below". This will just give us a gap between groups
Note: I've changed the colour of the rownum and columnnum text boxes as we can delete these once testing is complete.
The final design should look like this.
When we run the report and set the parameter to 2 we get this
set it to 3 and we get this
You can now remove the top row and middle column to get rid of the row and column numbers. If you want to have a group header as in your sample. Add a row inside the group again but this time at the top and then add an expression to give your desired title.
I do use InnoDB with MySQL
Hey,
I do have two tables:
First one is called adtells and contains very few elements and is rarely updated.
Second one contains a lot of elements and gets new inserts on a regular base.
The second table stores, which user has hidden an element out of the first table. I think I'm not able to join these tables.
My first query was something like this:
SELECT xy FROM firstTable WHERE 1 NOT IN (SELECT abc FROM secondTable)
My second approach are two queries:
The first selects all needed elements out of the second table. With those results, I access the first table.
What are your thoughts to those approaches? Is the first one or the second one more performant or do you have any other ideas?
Further explanation of the given example:
Table 1:
id | content
Table 2:
userId, tableOneId
The second table contains an assignment from a given user to an element of the first table. If there is an assignment, the affected tableOneId shall not be retrieved by the queries above.
Would love to hear from you!
Use NOT EXISTS
SELECT t1.* FROM firstTable T1
WHERE
NOT EXISTS
(SELECT 1 FROM secondTable T2 where t2.id = t1.id)
NOT EXISTS/EXISTS will terminate when the first match is found
IN will search all rows regardless of how many matches.. if there are 100 matches then 100 iterations.
Based on rule optimizer:
EXISTS is much faster than IN, when the sub-query results is very
large. IN is faster than EXISTS, when the sub-query results is very
small. Based on cost optimizer:
There is no difference.
Difference between EXISTS and IN in SQL?
Whenever I have two tables I want to join where some of the rows will have matches and some won't, I can't figure out how to get around the issue of the column I'm using for the ON condition getting overwritten with '' when it doesn't have a match.
Here is an example query:
SELECT * FROM kickstarter
LEFT JOIN user_kick_ratings
ON kickstarter.project_id=user_kick_ratings.project_id
WHERE rating>=1
Now wherever there is a row from 'kickstarter' where there isn't a matching row from user_kick_ratings, the project_id gets overwritten to ''. The only ways around this I know right now are a) make the id column names different or b) name aliases in the column select area which would force me to name every column I need, which is a lot.
I don't like either of those options, optimally. Is there a way I can use a different type of join or rearrange my query so that the project_id from the main table (kickstarter) is always there?
edit: I'll add that I DO need every row from 'kickstarter' that matches the query, but that there won't always be a corresponding row for the second table, if that wasn't already clear.
The cause of this has to do with the order of query execution. The query will first join all rows (regardless of a match, since it's a left join) and then it will filter out rows that don't meet the condition rating >= 1, effectively dropping any rows that didn't have a match in the first place.
To correct this, you need to change your join to only join when rating >= 1. This way, you can still get all rows from the first table, and only get matches from the second table that you need. Try this:
SELECT *
FROM kickstarter k
LEFT JOIN user_kick_ratings ukr
ON k.project_id = ukr.project_id AND ukr.rating >= 1;
As far as the overwritten id, you should instead rewrite your query to only select relevant columns. There's no need to select project_id from both tables, since they are always the same. You should select it from the table that is guaranteed to have a value; In this case, kickstarter:
SELECT k.project_id, k.stuff, ukr.rating
FROM ...
Figured it out, and it's so simple! Just use RIGHT JOIN and flip the table order. Even though it's simple, I hope this helps someone one day.
SELECT * FROM user_kick_ratings
RIGHT JOIN kickstarter
ON kickstarter.project_id=user_kick_ratings.project_id
WHERE rating>=1
For simple cases:
Instead of doing a SELECT *, you can use
SELECT table2.*, table1.* -- notice the reverse order!
FROM table1
LEFT JOIN table2 .....
They overwrite each other in the order of reference.
So now you got the id from table1.
Is there a way to have one column equal the count of all the rows in a different table where the id = a column in the current row?
For example.
table1 has the columns: id, count
table2 has the columns id, table1_id
I want the table1.count to automatically be filled with the amount of rows in table2 where table2.table1_id = table1.id
(its a parent child has one relationship).
Obviously i can just do this with php, i just figured this would be faster than to have to recount this constantly using php every time the page loads. Thanks.
You can accomplish this with a view. It will probably recalculate the number each time, though.
To update a regular table each time another one is changed, use a trigger.
Don't worry too much about recalculationif the table is seldom changed bcause the result will usually be in the query cache.
Using a view and a table table1_data, you could do this:
CREATE VIEW table1 AS
SELECT table1_data.*, COUNT(*) AS count
FROM table1_data, table2
WHERE table1_data.id = table2.table1_id
GROUP BY table1_data.id
This will take all the data from table1_data, add a column count as you described it, and present the result as a view which can be used just like a table in most situations.
Assuming table1.id is a unique key, you can do the following:
REPLACE INTO table1 (id, count)
SELECT table1_id, COUNT(*)
FROM table2
GROUP BY table1_id
You can achieve this "automatic" effect using triggers, of course if your DB engine supports them.
You would need to establish 2 triggers on your table_data, onInsert() and onDelete().
I have a database with three tables and I need to cross reference the first table against the other two to create a fourth table of consolidated information. All the tables have one field which is common, this is the MSISDN (mobile / cell telephone number) and is at least 10 digits long.
Table 1 - 819,248 rows
Table 2 - 75,308,813 rows
Table 3 - 17,701,196 rows
I want to return all the rows from Table 1 and append some of the fields from Tables 2 and Table 3 when there's a matching MSISDN.
My query has been running now for over 24 hours and I have no way of knowing how long something like this should take.
This type of query may be a regular project - is there a way to significantly reduce the query time?
I have indexed tables 2 and 3 with MSISDN and the fields I need to return.
My query is like this:
create TABLE FinishedData
select
Table1.ADDRESS, table1.POSTAL, table1.MOBILE,
table1.FIRST, table1.LAST, table1.MID, table1.CARRIER,
table1.TOWN, table1.ID, table2.status as 'status1',
table2.CurrentNetworkName as 'currentnetwork1',
table2.DateChecked as 'datechecked1', table3.Status as 'status2',
table3.CurrentNetworkName 'currentnetwork2',
table3.DateChecked as 'datechecked2'
from
table1 left join (table2, table3)
on (right(table1.MOBILE, 10) = right(table2.MSISDN, 10)
AND right(table1.MOBILE,10) = right(table3.MSISDN,10))
MySQL is running on a 64bit windows machine with 12GB memory and 8 logical cores # 3GHz. MySQLd is only using 10% cpu and 600MB of resources when running the query.
Any help is appreciated.
The kill performance issue is with right function When you use this function, MySQL can't use indexes.
My suggest is:
Create new fields in table2 and table 3 with reverse content of MSISDN
Make the join replacing right function by left function.
With this little change MySQL will can take indexes to make your joins.
Explained steps:
1) Create new columns:
Alter table table2 add column r_MSISDN varchar(200);
update table2 set r_MSISDN = reverse( MSISDN );
Alter table table3 add column r_MSISDN varchar(200);
update table3 set r_MSISDN = reverse( MSISDN );
2) New join:
...
from
table1 left join (table2, table3)
on (right(table1.MOBILE, 10) = left(table2.r_MSISDN, 10)
AND right(table1.MOBILE,10) = left(table3.r_MSISDN,10))
RIGHT is a function. Using a function in where clause means MySQL (and perhaps any database) cannot use an index because it has to compute the value returned by the function for each row before comparing.
If you want to make this query any faster, consider storing the MSISDN in a normalized form and comparing using = operator.
Now I am not sure what MSISDN number looks like. If it is a fixed width number then your job is easy. If it contains separators (spaces/hyphens) and the separators are only there for readability you should remove them before storing in database. If the first 10 characters are important and remaining are optional, you might consider storing the first 10 and remaining characters in separate columns.
As others have already mentioned, the problem is with the right function which does not allow using any indexes.
In simple words, your current query for each row in table1 makes a full scan of table2 and for each match makes a full scan of table3. Considering how many rows you have in table2 and table3, you have a good chance to see the world before the query is finished.
Another problem is that the query initiates a huge transaction which should be able, as MySQL thinks, to be rolled back and you might think over the isolation level.
I would not change the current tables though. I would create subcopies of table2 and table3 with the required columns, and add the right(table2.MSISDN, 10) as a separate indexed column in table2 copy (right(table3.MSISDN,10) in table3 copy).
Then, you can do the LEFT JOIN with the copies, or even reduce the copies to the rows which do match anything in table1 and do the LEFT JOIN then.