Присоединитесь к генератору месяцев по вашему запросу:
select to_char(to_date(mth_num, 'MM'), 'MONTH') month, nvl(cnt, 0) cnt
from (
select count(emp_id) as cnt, to_char(due_date, 'mm') mth_num
from emp_request where due_date is not null
group by to_char(due_date, 'mm')) e
right join (
select to_char(level, 'fm00') mth_num
from dual connect by level <= 12) m using (mth_num)
order by mth_num
dbfiddle demo sup>
Генератор месяцев - это простой иерархический запрос, который дает нам 12 значений 01
, 02
... 12
:
select to_char(level, 'fm00') mth_num from dual connect by level <= 12
Вы также можете использовать системные представления для получения этих чисел: [ 1114]
select to_char(rownum, 'fm00') mth_num from all_objects where rownum <= 12
или этот синтаксис:
select to_char(column_value, 'fm00') mth_num
from table(sys.odcivarchar2list(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12))
Лучше работать с числами, которые можно правильно отсортировать и преобразовать в названия месяцев на последнем шаге. Таким образом, у вас есть естественный месячный порядок. Если вы хотите быть уверены, что названия месяцев всегда на английском языке, не зависят от локальных настроек, используйте to_date
с третьим параметром, как здесь:
select to_char(sysdate, 'month', 'nls_date_language=english') from dual
Коллекция, используемая в foreach, является неизменной. Это очень много задумано.
Как сказано в MSDN :
Оператор foreach используется для перебрать коллекцию, чтобы получить информация, которую вы хотите, но можете не использоваться для добавления или удаления элементов из исходной коллекции, чтобы избежать непредсказуемые побочные эффекты. Если вы необходимо добавить или удалить элементы из В исходной коллекции используйте цикл for.
Пост в ссылке , предоставленной Poko, указывает, что это разрешено в новых одновременных коллекциях.
Вот как вы можете это сделать (быстрое и грязное решение. Если вам действительно нужен такой вид поведения, вы должны либо пересмотреть свой дизайн, либо переопределить все члены IList
и собрать список источников):
using System;
using System.Collections.Generic;
namespace ConsoleApplication3
{
public class ModifiableList<T> : List<T>
{
private readonly IList<T> pendingAdditions = new List<T>();
private int activeEnumerators = 0;
public ModifiableList(IEnumerable<T> collection) : base(collection)
{
}
public ModifiableList()
{
}
public new void Add(T t)
{
if(activeEnumerators == 0)
base.Add(t);
else
pendingAdditions.Add(t);
}
public new IEnumerator<T> GetEnumerator()
{
++activeEnumerators;
foreach(T t in ((IList<T>)this))
yield return t;
--activeEnumerators;
AddRange(pendingAdditions);
pendingAdditions.Clear();
}
}
class Program
{
static void Main(string[] args)
{
ModifiableList<int> ints = new ModifiableList<int>(new int[] { 2, 4, 6, 8 });
foreach(int i in ints)
ints.Add(i * 2);
foreach(int i in ints)
Console.WriteLine(i * 2);
}
}
}
Сделайте копию перечисления, используя в этом случае метод расширения IEnumerable, и перечислите его. Это добавит копию каждого элемента в каждом внутреннем перечисляемом для этого перечисления.
foreach(var item in Enumerable)
{
foreach(var item2 in item.Enumerable.ToList())
{
item.Add(item2)
}
}
Вы действительно должны использовать для ()
вместо foreach ()
в этом случае.
Вы не можете изменить перечисляемую коллекцию во время ее перечисления, поэтому вам придется внести изменения до или после перечисления.
Цикл для
является хорошей альтернативой, но если ваша коллекция IEnumerable
не реализует ICollection
, это невозможно.
Либо:
1) Сначала скопируйте коллекцию. Перечислите скопированную коллекцию и измените исходную коллекцию во время перечисления. (@tvanfosson)
или
2) Вести список изменений и фиксировать их после перечисления.
Как уже упоминалось, но с примером кода:
foreach(var item in collection.ToArray())
collection.Add(new Item...);